Bevy 0.16 状态管理初学者指南
ZoOL 撰写的 Bevy 状态系统完整入门教程,目标版本 0.16。
核心观点
状态是应用程序级的有限状态机,决定系统执行流程,与属于特定实体的组件不同,状态是影响每帧运行哪些系统的全局资源。
状态定义
#[derive(States, Default, Debug, Clone, Eq, PartialEq, Hash)]
enum GameState {
#[default]
MainMenu,
Loading,
InGame,
Paused,
GameOver,
}必需 trait: States + Default + Debug + Clone + Eq + PartialEq + Hash
0.16 新 API
// 旧: add_state::<T>()
// 新: init_state::<T>() — 自动使用 Default 作为初始状态
App::new()
.init_state::<GameState>()
.init_state::<PausedState>()多状态系统
可定义多个独立状态类型,同时管理不同关注点:
AppState- 应用程序流(Menu / InGame / Settings)PausedState- 暂停状态(Running / Paused)
运行条件
.add_systems(Update, (
menu_system.run_if(in_state(GameState::MainMenu)),
gameplay_system.run_if(in_state(GameState::InGame)),
pause_system.run_if(in_state(GameState::Paused)),
))组合多状态:
active_gameplay_system
.run_if(in_state(AppState::InGame))
.run_if(in_state(PausedState::Running))转换调度
| 调度 | 用途 | 运行次数 |
|---|---|---|
OnEnter(S) | 初始化、生成实体、加载资源 | 每次进入时一次 |
OnExit(S) | 清理、保存数据、资源管理 | 每次离开时一次 |
Update + run_if(in_state(S)) | 每帧运行的逻辑 | 每帧 |
状态转换
fn handle_menu_input(
mut next_state: ResMut<NextState<GameState>>,
input: Res<ButtonInput<KeyCode>>,
) {
if input.just_pressed(KeyCode::Enter) {
next_state.set(GameState::InGame);
}
}重要: 状态转换发生在 StateTransition 调度期间,在 PreUpdate 之后、Update 之前。
0.16 新功能: StateScoped
// 启用
app.enable_state_scoped_entities::<GameState>();
// 使用
commands.spawn((
StateScoped(GameState::InGame),
Player,
Health { current: 100, max: 100 },
));`离开状态时自动销毁实体**,无需手动编写 cleanup 系统。
完整示例
教程包含一个可运行的完整游戏状态机示例,涵盖:
MainMenu→InGame→Paused→GameOver循环StateScoped自动清理OnEnter/OnExit设置与销毁- 多状态组合运行条件
文件位置
/Users/zool/workspace/ZoOL's Valut/Bevy 0.16 状态管理初学者指南.md