Bevy ECS 游戏架构
将以下提示词粘贴到你的 AI 对话框中:
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_3c6cb52e/bevy-ecs-eoe8。
技能介绍
你要解决的问题
Bevy 的 API 在每个 minor 版本都会变动:Bundle 在 0.15 被标记废弃、0.16 直接移除,delta_seconds() 改名成 time.delta_secs(),Camera2dBundle/SpriteBundle 查不到,旧教程里的 buffered-event 用法也和当前版本对不上。与此同时,ECS 的写法有自己的一套约束:两个系统同时写同一组件会触发 conflicting accesses panic,Commands 是延迟执行的,本帧 spawn 的实体要到同步点之后才能被 Query 看到,而默认并行调度意味着「系统 B 在 A 之后跑」只是错觉。对刚上手 Bevy 的工程师来说,这些坑往往要用一次崩溃才能换来一条经验。
这个技能覆盖什么
核心能力:
- 锁定版本:在
Cargo.toml里固定bevy = "0.16"(或你的目标版本),以匹配版本的文档为准,开发环境开启dynamic_linking加快迭代。 - 组装 App:
App::new().add_plugins(DefaultPlugins)拿到 windowing、input、rendering、time 等能力,把系统注册进Startup与Update。 - 建模数据:
#[derive(Component)]描述实体数据,#[derive(Resource)]描述全局唯一数据(分数、设置、时钟)。 - 写系统:普通函数即系统,参数声明数据访问——
Query取实体、Res/ResMut读写资源、Commands做延迟 spawn/despawn;访问不冲突时系统自动并行。 - 调度控制:用
.chain()或显式约束只排序真正有依赖的系统,用run_if加运行条件,把相关配置归拢到Plugin。
典型工作流:
- 固定版本,把匹配的文档当作事实来源。
- 构建 App 并注册进 schedule。
- 用组件和资源划分数据。
- 用 Query 写系统,运动一律乘
time.delta_secs(),保证帧率无关。 - 用
cargo run编译运行,直接读 Bevy 在启动时报出的冲突查询。
适用边界与注意点
这是 ECS 核心层技能,不涉及渲染管线、自定义 shader、UI 布局和音频,那些是独立话题。
常见坑位清单:
- 忘记
#[derive(Component)]/#[derive(Resource)]会报 trait 未实现。 - 运动速度随帧率变化——永远乘
time.delta_secs(),不要假设固定帧间隔。 - 同一系统里两个 Query 写同一组件 → 用
With/Without切分实体,或改用ParamSet。 - 同帧内后面系统读不到刚 spawn 的实体 →
Commands在同步点才生效,放到后续系统读。 - 默认并行调度不保证顺序 → 需要时显式
.chain()。 - 旧 Bevy 代码片段不可混用,按你锁定的版本查文档。
如果你要做引擎无关的 AI 逻辑或过程化生成,可配合 game-ai / procedural-gen 技能使用;项目较轻量时,pygame-core / love2d-core 也是更简单的替代。
使用场景
- 初次用 Bevy 0.16+ 搭建项目骨架时,需要正确注册 DefaultPlugins 并把系统安排进 Startup 与 Update 调度。
- 游戏里有一批会移动的实体,需要用 Query 写系统并乘以 time.delta_secs(),让速度不受帧率影响。
- 启动时收到 conflicting accesses panic,需要判断两个 Query 是否写了同一组件,并用 With/Without 或 ParamSet 解决。
- 从 0.14/0.15 教程迁移代码,遇到 Camera2dBundle 找不到或 delta_seconds() 无法编译,需要按 0.16 新写法改写。
适合人员
- 正在把桌面 Rust 项目迁移到 Bevy 0.16+ 的引擎工程师,需要处理 API 变更与调度细节。
- 用 Bevy 开发 2D 小游戏的独立开发者,想按组件/资源/系统的范式组织游戏逻辑。
- 调试 borrow 冲突 panic 的 Rust 工程师,需要定位查询重叠并调整系统顺序。
- 在团队代码评审中负责规范 Bevy ECS 写法的资深开发者,希望统一插件、调度和查询的约定。