用途
本技能用于在 Bevy 0.20+ 中按 ECS 组合方式组织游戏逻辑:把玩法数据拆分到多个小型组件与系统中,而不是用一个类型承载实体的全部字段。当需要生成组件元组、用 With 过滤 Query、为相互依赖的系统排序时使用。
主要能力
- 组件:Rust 结构体派生 Component。示例把 Person 与 Name 拆开,使多种实体都能携带名字。
- 实体生成:在 Startup 系统中通过 Commands 生成组件元组,例如 commands.spawn((Person, Name(...)))。
- 系统与查询:系统是函数。Query<&Name, With<Person>> 读取同时具有 Person 的实体上的名字;Query<&mut Name, With<Person>> 写入。通过 add_systems 注册。
- 调度:Startup 只运行一次,Update 在其后运行。除非调用 .chain(),系统并行执行。示例把 update_people 与 greet_people 链式排序,并把无关系统留在链外。
- 父子关系:父实体与子实体使用 ChildOf。
- 变更检测:使用 Changed。
组合选择对照
- 一个对象上的“拥有”部件:在同一实体上放多个 Component 结构体。
- 行为:对 Query 的系统函数。
- 启动时生成:Startup 系统中的 Commands。
- 有序步骤:对相互依赖的系统调用 .chain()。
- 父与子:子实体上的 ChildOf。
使用方式(示例要点)
Cargo 依赖为 bevy = "0.20"。示例中 PeoplePlugin 在 Startup 注册 spawn_people,在 Update 注册 (update_people, greet_people).chain(),并单独注册只读 Name 的 count_names,使其留在写入链之外。FamilyPlugin 示例展示父实体、带 ChildOf 的子实体,以及用 Changed<Name> 在名字变化时运行的系统。
状态归属与借用规则
- 单个实体上的数据:Component,由某个系统通过 Query 修改,位于 Update 或 FixedMain。
- 整个应用的一个值:Resource,由一个系统修改,Startup 插入,之后由读取它的调度使用。
- 生成:Commands,由生成它的系统负责;初始世界用 Startup,运行时生成用后续调度。
- 不能竞态的次序:.chain(),仅作用于被链式的系统,位于同一调度。
- 插件边界:Plugin,build 在应用运行前注册系统与资源。
借用规则:两个都可变查询同一组件的系统必须排序(.chain()),或拆分到只有一个写入。无关系统保持并行。
适用场景
需要按 ECS 惯用法拆分实体数据与行为、需要稳定模拟步(FixedMain 与 Fixed 时钟)、需要启动时生成实体、需要跨系统通知但不共享状态(见 bevy-events-messaging)时适用。
限制与禁止事项
- 文档 URL 不要固定 /0.20.0/,链接保持最新,0.20 目标只在正文说明一次。
- 不要从两个无序系统可变查询同一组件。
- 不要在此发明物理、导航、网络或 XR crate;本技能只命名有文档的 Bevy crate 与模块。
- 不要用单一组件存储实体的全部行为。
- 不要使用本文件未打开的 Bundle API,不要使用第三方 crate。
- 编辑器控件树不在范围内;此处的组合指实体、组件与系统。
相关技能
前置:bevy-master(状态归属)、bevy-project-foundations(crate 与 App 外壳)。互补:bevy-data-resources(不应作为组件的应用级数据)、bevy-events-messaging(非共享组件的跨系统通知)。下游:bevy-character-movement(固定时间步上的移动组件与系统)。主路由:bevy-master。