SuperAPI AI 工具集

bevy-project-foundations

编程与开发

查看项目

更新于 10-16 06:08

技能介绍

用途

当一个新的 Bevy 应用需要一个 crate、一个版本锁定,以及在玩法系统出现之前为功能代码预留位置时,加载本技能。文中提到的文件夹名称只是布局习惯,并非引擎类型。

主要能力

ECS 形态

  • Crate:使用 cargo new 创建,并添加锁定在 0.20 的 bevy 依赖。
  • Features:默认会引入窗口、输入和渲染。只有当二进制应保持无头时才关闭 default-features。
  • App shell:App::new()、插件,然后在该 App 上添加系统和资源。
  • 代码布局:在普通 Rust 模块中按功能拆分。引擎并不要求特定的目录树。

锁定 crate 并保持 dev 构建可用

Bevy 默认的 debug profile 会以未优化方式编译依赖,因此 dev profile 提升依赖的 opt-level,同时让游戏 crate 本身仍易于单步调试。

[package]
name = "game"
version = "0.1.0"
edition = "2021"

[dependencies]
bevy = "0.20"

[profile.dev]
opt-level = 1

[profile.dev.package."*"]
opt-level = 3

无头工具 crate 会去掉默认 feature 集,只添加该二进制实际调用的内容。

[dependencies]
bevy = { version = "0.20", default-features = false }

带窗口的游戏会接入 DefaultPlugins 和一个功能插件。GameConfig 是在第一个 schedule 运行前插入的应用级状态。

#[derive(Resource)]
struct GameConfig {
    title: String,
}

fn boot(config: Res<GameConfig>) {
    let _title = config.title.as_str();
}

pub struct GamePlugin;

impl Plugin for GamePlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(GameConfig {
            title: "Game".to_string(),
        })
        .add_systems(Startup, boot);
    }
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(GamePlugin)
        .run();
}

第二个模块拥有一个功能。插件就是边界。系统留在声明其组件的模块中。

#[derive(Component)]
struct Player;

fn spawn_player(mut commands: Commands) {
    commands.spawn(Player);
}

pub struct PlayerPlugin;

impl Plugin for PlayerPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(Startup, spawn_player);
    }
}

布局选择

需求 Bevy 惯用法
新建 crate cargo new 加上 bevy 依赖
窗口、输入、渲染 bevy crate 上的 Cargo features 和 profiles
功能拆分 由你选择的 Rust 模块
项目文件 Cargo.toml 加上 Rust 模块

使用方式

范围

在 Cargo.toml 中锁定 bevy = "0.20"。DefaultPlugins 会引入该 crate feature 所启用的窗口、输入和音频后端。

Workspace 成员和命名 linter 都是普通 Cargo 内容。本技能不会发明文件夹强制器。

专家知识增量

目标:Bevy 0.20+。

核心 ECS 类型:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息和观察者属于一个归属槽位,其 API 见 bevy-events-messaging。除非 .chain() 对冲突的系统排序,否则系统会并行运行。

谁拥有状态

部分 所有者 谁可以修改 Schedule
单个实体上的数据 Component 一个系统通过 Query Update 或 FixedMain
整个应用的一个值 Resource 一个系统 Startup 插入,然后由读取它的 schedule
生成 Commands 执行生成的系统 初始世界用 Startup;运行时生成用后续 schedule
不能竞态的顺序 .chain() 仅被链式的系统 同一 schedule
插件边界 Plugin build 注册系统和资源 应用运行之前

借用规则:两个系统若都对同一组件进行可变查询,必须排序(.chain())或拆分,使只有一个写入。不相关的系统保持并行。这是 ECS 页面规则,不是对 system-set API 的猜测。

决策

如果你需要 这样做 不要
每实体数据 Component + Query 放在 World 之外的自由浮动 struct
应用级配置或时钟 Resource 把值复制到每个实体上
稳定的模拟步长 FixedMain 和 Fixed 时钟 把模拟绑定到原始帧 Update
启动时生成 Startup 中的 Commands 从渲染系统生成
非共享状态的跨系统通知 bevy-events-messaging 中的消息或观察者槽位 在本文件中发明新的事件类型
文档集合之外的 API 先查官方文档 编造的 crate 或 API

加载 references/ecs-ownership.md 查看归属表。

NEVER

  • 不要在文档 URL 中锁定 /0.20.0/。原因:链接保持在 latest;0.20 目标只在正文中陈述一次。
  • 不要从两个无序系统对同一组件进行可变查询。原因:除非 .chain() 排序,否则 schedule 会并行运行系统。
  • 不要在此发明物理、导航、网络或 XR crate。原因:本技能只命名有文档记录的 Bevy crate 和模块。
  • 此 crate 中不要使用场景树项目类型或 autoload 单例。原因:Bevy 代码保持惯用 ECS,并只使用有文档记录的 Bevy API。
  • 不要发明本技能所列 profiles 之外的 Cargo features。原因:Bevy 代码保持惯用 ECS,并只使用有文档记录的 Bevy API。
  • 不要使用第三方 crate。原因:Bevy 代码保持惯用 ECS,并只使用有文档记录的 Bevy API。

适用场景

  • 启动带窗口的 Bevy 应用。
  • 启动无头(headless)的 Bevy 应用。
  • 在玩法系统存在之前搭建 crate、版本锁定和功能代码位置。

限制

  • 目标为 Bevy 0.20+。
  • 只命名有文档记录的 Bevy crate 和模块,不涉及物理、导航、网络或 XR crate。
  • 不使用第三方 crate。
  • 不发明 Cargo features 或 API。
  • 消息和观察者的 API 需参考 bevy-events-messaging,本技能不展开。

参考

  • bevy-master 上的库锁定保持 0.20。

官方文档

  • Getting started - cargo new / cargo add bevy。
  • Apps - App::new()、World 和 Schedule。
  • Examples - latest 分支上的示例树。

相关技能

前置:

  • bevy-master - 库锁定以及接下来加载哪个 Bevy 技能。

互补:

  • bevy-ecs-composition - crate 存在之后的实体、组件和系统。

下游 / 消费者:

  • bevy-app-resources - App 存在之后的应用级资源。

主控:

  • bevy-master - Bevy 路由器。