Bevy States 生命周期时序问题

Bevy States 系统的生命周期钩子(on_enteron_updateon_exit)执行时机常与直觉不符,存在已知的时序模糊性。

已知 Issue

  • **Issue 7633OnEnter 对默认状态的触发时机晚于预期。开发者期望在 App::build() 阶段完成后立即触发默认状态的 OnEnter,但实际上可能延迟到第一帧的 StateTransition 调度期间
  • **Issue 17708:States / 生命周期钩子的时序模糊——标题级 issue,涵盖 on_updateon_exit 等多个钩子与预期执行顺序的偏差

时序模糊的具体表现

钩子直觉预期实际行为
OnEnter(默认状态)应用启动后立即执行延迟到第一帧 PreUpdate 之后的 StateTransition 期间
OnExit状态离开前一帧的最后一件事可能在状态转换命令发出后的同一帧执行,也可能在下帧
OnUpdate只要处于该状态就每帧执行StateTransition 调度位置影响,状态切换帧可能少执行一次

这种模糊性源于状态转换发生在固定的 StateTransition 调度期间(PreUpdate 之后、Update 之前),而开发者往往假设状态转换是“瞬间”发生的。

与 Event 系统的关联

状态生命周期钩子和 Events 系统共享同一种时序哲学:默认延迟、时序黑箱。两者都依赖框架内部的调度顺序,而非开发者显式控制的查询语义。

应对策略

  1. 不依赖精确时序:把 OnEnter 视为“进入后的某个时刻”而非“进入瞬间”
  2. 用组件存在性替代回调:如 Unity DOTS 的 System State Components 模式——查询 Has<StateA> 的实体,而非依赖 OnEnter(StateA) 的钩子
  3. 显式帧计数:在 OnEnter 中记录进入帧号,用帧号差判断“进入后第 N 帧”再执行敏感操作
  4. 避免在 OnEnter 中发事件:因为事件本身又有帧延迟,两层延迟叠加会导致难以调试的时序 bug

相关页面