使用 Handle 将资产加载到 Bevy 引擎并稍后使用资产的正确方法是什么?

Nam*_*ord 4 game-development rust bevy

我正在学习 Rust 和 Bevy 引擎,我希望Font在整个应用程序生命周期中保持加载某些资产(例如 s)。


// Resource for fonts:
#[derive(Default, Clone)]
pub struct ResFont {
    pub ui: Handle<Font>, // The font that will be used in this example.
    pub dialog: Handle<Font>,
    ...
}

// Insert resource in main() during App building:
{
    .insert_resource(ResFont::default())
}

// Load resource during startup:
pub fn startup(asset_server: Res<AssetServer>, mut res_font: ResMut<ResFont>)
{
    res_font.ui = asset_server.load("font/Default.ttf");
}

// Use the font resource in a different place:
pub fn setup_ui(res_font: ResMut<ResFont>)
{
    ...
    TextStyle {
        font: res_font.ui.clone(), 
        font_size: 12.0,
        color: Color::WHITE,
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

setup_ui()在底部的函数中,我用来.clone()复制该资产。如果我不使用.clone(),我会收到错误:

cannot move out of dereference of `bevy::prelude::ResMut<'_, resource::text::ResFont>`

move occurs because value has type `bevy::prelude::Handle<bevy::prelude::Font>`, which does not implement the `Copy` traitrustc(E0507)

ui.rs(19, 27): move occurs because value has type `bevy::prelude::Handle<bevy::prelude::Font>`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  1. 我在操作过程中是否将整个内容复制Font到这里.clone()

  2. 这是保持资源加载并供以后使用的“正确”方法,还是有更好的方法来实现这一点,我不知道?

小智 7

关于您的问题,我建议您阅读(非官方)bevy cheatbook 关于资产的章节,它将回答您的大部分问题。我将在这里引用与您的问题相关的部分:

  1. 不,你不是复制Font,只是复制Handle.

句柄具有内置的引用计数(类似于 Rust 中的 Rc/Arc)。这使得 Bevy 能够跟踪资产是否仍然需要,并在不再需要时自动卸载。您可以使用 .clone() 为同一资源创建多个句柄。克隆是一种廉价的操作,但它是显式的,以确保您了解代码中创建额外句柄并可能影响资产生命周期的位置。

  1. 这是两种建议的方法之一。

您可以将句柄存储在方便的地方(例如资源中)。如果您没有将句柄存储在任何地方,您始终可以通过调用 asset_server.load 从路径生成句柄。您可以在需要时简单地执行此操作,而不必费心存储句柄。

重复调用asset_server.load有效,因为该函数在内部检查资产是否已加载并重用该资产。(这可以在该方法的源代码中看到AssetServer::load_async,特别是l.246-252)。

那么什么时候在资源中存储句柄优于呢asset_server.load?如果不再存在该资产的句柄,资产服务器将卸载该资产。对于 UI 中使用的字体来说,这种情况通常不太可能发生,但对于您希望始终保持加载状态的其他类型的资源来说,这种情况可能更常见。将句柄存储在资源中可确保它永远不会被卸载。

您的代码的一些其他提示:

  • 而不是.insert_resource(ResFont::default())您可以只使用.init_resource(ResFont),然后它会调用Default实现。
  • 在 中pub fn setup_ui(res_font: ResMut<ResFont>),您可以直接使用Res<ResFont>,因为您不会改变它。

为了供将来参考,此回复适用于 Bevy 0.5。