用途
Bevy Sandbox(薄路由)是一个类型路由技能,用于处理玩家建造实体的放置(place)、移除(remove)与保存(save)。它本身不实现领域逻辑,而是将具体工作路由到其他 Bevy 技能。
主要能力
- 放置单元格:按下按键时生成带有类型 id 的 PlacedCell 组件。
- 编辑单元格:通过 .chain() 先执行 paint 再执行 remove,例如 x = 0 处 kind 1 变为 kind 2,kind 0 则被 despawn。
- 构建快照:将 PlacedCell 查询结果映射为 serde 可序列化的 CellRecord 记录,存入 BuildSnapshot 资源,实现构建的往返(round-trip)。
ECS 结构
- 组件(Component)以纯数据保存每实体的类型标记,本文件不命名新的引擎类型。
- 资源(Resource)通过 bevy-data-resources 保存运行期计数器(分数、波次索引、种子)。
- 系统在 Update 或来自 bevy-master 的固定时间步读取组件;当后续系统需要看到结果时,用 .chain() 排序。
- 游戏模式变更通过 bevy-state-machines 处理;本文件仅注册放置、编辑和构建快照。
路由
- bevy-3d-world-building:道具。
- bevy-inventory-system:建造部件。
- bevy-save-load:世界持久化。
- bevy-input-handling:放置。
范围
已放置的单元格是一个带有网格坐标和类型 id 的组件。道具、库存和文件持久化保留在上述链接的技能中。
依赖
[dependencies]
bevy = "0.20"
serde = { version = "1", features = ["derive"] }
代码示例
放置单元格:
#[derive(Component, Clone, Copy)]
struct PlacedCell {
x: i32,
y: i32,
z: i32,
kind: u16,
}
fn place_cell(keys: Res<ButtonInput<KeyCode>>, mut commands: Commands) {
if keys.just_pressed(KeyCode::KeyP) {
commands.spawn((
PlacedCell {
x: 0,
y: 0,
z: 0,
kind: 1,
},
Transform::from_xyz(0.0, 0.0, 0.0),
));
}
}
pub struct PlacePlugin;
impl Plugin for PlacePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, place_cell);
}
}
编辑单元格:
#[derive(Component, Clone, Copy)]
struct PlacedCell {
x: i32,
y: i32,
z: i32,
kind: u16,
}
fn remove_empty(mut commands: Commands, cells: Query<(Entity, &PlacedCell)>) {
for (entity, cell) in &cells {
if cell.kind == 0 {
commands.entity(entity).despawn();
}
}
}
fn paint_neighbor(mut cells: Query<&mut PlacedCell>) {
for mut cell in &mut cells {
if cell.x == 0 && cell.kind == 1 {
cell.kind = 2;
}
}
}
pub struct EditPlugin;
impl Plugin for EditPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, (paint_neighbor, remove_empty).chain());
}
}
构建快照:
use serde::{Deserialize, Serialize};
#[derive(Component)]
struct PlacedCell {
x: i32,
y: i32,
z: i32,
kind: u16,
}
#[derive(Serialize, Deserialize, Clone, Default)]
struct CellRecord {
x: i32,
y: i32,
z: i32,
kind: u16,
}
#[derive(Resource, Default)]
struct BuildSnapshot(Vec<CellRecord>);
fn snapshot(cells: Query<&PlacedCell>, mut saved: ResMut<BuildSnapshot>) {
saved.0 = cells
.iter()
.map(|cell| CellRecord {
x: cell.x,
y: cell.y,
z: cell.z,
kind: cell.kind,
})
.collect();
}
pub struct SnapshotPlugin;
impl Plugin for SnapshotPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<BuildSnapshot>()
.add_systems(Update, snapshot);
}
}
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_plugins(SnapshotPlugin)
.run();
}
专家知识要点
目标:Bevy 0.20+。
核心 ECS 类型:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于所有权槽位,其 API 见 bevy-events-messaging。除非 .chain() 对冲突系统排序,否则系统并行运行。
状态所有权:
- 单个实体上的数据:组件,由一个系统通过 Query 修改,运行于 Update 或 FixedMain。
- 整个应用的一个值:资源,由一个系统修改,Startup 插入,随后由读取它的调度使用。
- 生成:Commands,由生成系统负责,Startup 用于初始世界,后续调度用于运行时生成。
- 不可竞争的排序:.chain(),仅作用于被链式连接的系统,同一调度内。
- 插件边界:Plugin,build 注册系统与资源,在应用运行前。
借用规则:两个都可变查询同一组件的系统必须排序(.chain())或拆分,使只有一个写入。无关系统保持并行。
决策表:
- 需要每实体数据:用组件 + Query,不要用所有实体共享的一个可变块。
- 需要应用级配置或时钟:用资源,不要把值复制到每个实体。
- 需要稳定模拟步:用 FixedMain 和 Fixed 时钟,不要把模拟绑定到原始帧 Update。
- 需要 Startup 生成:在 Startup 中用 Commands,不要从渲染系统生成。
- 需要跨系统通知而非共享状态:用 bevy-events-messaging 中的消息或观察者槽位,不要在本文件发明新事件类型。
- 行为已由关联领域技能拥有:保持本路由仅含组件和资源,不要在本文件重复实现。
加载 references/ecs-ownership.md 查看所有权表。
禁止事项
- 不要在文档 URL 中固定 /0.20.0/。原因:链接保持最新;0.20 目标在正文中说明一次。
- 不要从两个无序系统可变查询同一组件。原因:除非 .chain() 排序,调度会并行运行系统。
- 不要在此发明物理、导航、网络或 XR crate。原因:本技能只命名有文档的 Bevy crate 和模块。
- 不要在同一无序对中 paint 单元格并 despawn 它。原因:两者都触及 PlacedCell 数据,因此 paint 需通过 .chain() 在 remove 之前运行。
- 不要发明类型 API。原因:Bevy 代码保持惯用 ECS,仅使用有文档的 Bevy API。
- 不要在此选择物理或网络 crate。原因:Bevy 代码保持惯用 ECS,仅使用有文档的 Bevy API。
参考
bevy-master 上的库固定为 0.20.0。官方页面保持在无版本站点。
官方文档:
- Assets - 官方资产目录。未选择第三方 crate。
- Examples - 最新分支上的示例树。
- ECS - Component、systems、Query、Startup、Update 和 .chain()。
- Plugins - Plugin、DefaultPlugins、MinimalPlugins 和 add_plugins。
相关技能
前置:
- bevy-master - ECS 所有权与调度。
- bevy-ecs-composition - 生成与查询形态。
补充:
- bevy-3d-world-building - 道具。
- bevy-inventory-system - 建造部件。
- bevy-save-load - 世界持久化。
- bevy-input-handling - 放置。
下游 / 消费者:无。本路由不拥有第二实现。
主技能:bevy-master - Bevy 路由。