资源

可参考的官方例子: ecs_guide.


资源允许你独立于实体存储一些数据类型的单一全局实例。

在你的应用程序中仅仅使用资源来存储真正的全局数据,例如配置/设置。

任何 Rust 类型(结构枚举)都可以作为资源使用。目前,不需要满足特殊的 trait 或应用 derive,但在未来的 Bevy 版本中可能会改变(类似于组件的要求)。

资源类型必须是唯一的,一个特定资源类型只能有一个实例。

struct GoalsReached {
    main_goal: bool,
    bonus: bool,
}

系统中可以通过 Res/ResMut 来访问资源。

资源初始化

为简单资源派生用于初始化默认值的 Default 方法:

#[derive(Default)]
struct StartingLevel(usize);

通过实现 FromWorld 方来满足资源更复杂的初始化需求:

struct MyFancyResource { /* stuff */ }

impl FromWorld for MyFancyResource {
    fn from_world(world: &mut World) -> Self {
        // You have full access to anything in the ECS from here.
        // For instance, you can mutate other resources:
        let mut x = world.get_resource_mut::<MyOtherResource>().unwrap();
        x.do_mut_stuff();

        MyFancyResource { /* stuff */ }
    }
}

你可以在 App 创建时初始化你的资源:

    fn main() {
        App::new()
            // ...

            // if it implements `Default` or `FromWorld`
            .init_resource::<MyFancyResource>()
            // if not, or if you want to set a specific value
            .insert_resource(StartingLevel(3))

            // ...
            .run();
    }

Commands 可以用来在从系统中创建/删除资源:

    commands.insert_resource(GoalsReached { main_goal: false, bonus: false });
    commands.remove_resource::<MyResource>();

如果你插入的资源类型已经存在,之前的将被覆盖。

使用建议

何时使用实体/组件、或何时使用资源来存储数据,通常是关于你想如何访问数据的问题:使用从任何地方全局访问的模式(资源),还是使用 ECS 模式(实体/组件)。

即使在你的游戏中某个对象只有一个(比如单人游戏中的玩家),使用实体而使用资源也是很合适的,因为实体是由多个组件组成的,其中一些组件可以与其他实体共用。这可以使你的游戏逻辑更加灵活。例如,你可以用一个"健康/伤害系统",对玩家和敌人都有效。