问题描述
我正在学习 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,}
...
}
在底部的函数 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
我有两个问题:
解决方法
关于您的问题,我建议您阅读(非官方)bevy cheatbook's chapter on assets,它会回答您的大部分问题。我将在此处引用与您的问题相关的部分:
- 不,您不是在复制
Font
,而是在复制Handle
。
句柄有内置的引用计数(类似于 Rust 中的 Rc/Arc)。这允许 Bevy 跟踪资产是否仍然需要,并在不再需要时自动卸载它。您可以使用 .clone() 为同一资产创建多个句柄。克隆是一种廉价的操作,但它是明确的,以确保您了解代码中创建额外句柄并可能影响资产生命周期的位置。
- 这是两种建议的方式之一。
您可以将句柄存储在您方便的地方(例如在资源中)。 如果您没有将句柄存储在任何地方,您始终可以通过调用 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。