Latest commit 1970b9e
系统执行顺序
Bevy 的调度算法会尽量多线程地运行多个系统,前提是不发生数据竞争。当一个系统可变地访问某个数据,而另一个系统也访问同一数据,那么这两个系统就不能同时运行。Bevy 可以从系统的参数知道是可变访问还是不可变访问。
默认情况下,系统执行顺序不确定。Bevy 不关心这些系统什么时候运行,甚至每一帧都会有不同的系统执行顺序!
这里有什么问题?
多数情况下,无需担心系统执行顺序。但是有时要让系统按特定顺序执行:
- 涉及数据修改顺序:一个系统修改数据,而另一个系统访问数据。
- 涉及事件:一个系统发送事件,另一个系统接收事件。
- 正在使用 [Change Detection]。
系统以错误的顺序运行会导致某些行为延迟到下一帧(查看[Avoiding Frame Delays / 1-frame-lag]),甚至产生严重的 bug。系统执行顺序是否重要取决于具体游戏逻辑。偏重视觉的游戏可能并不在乎延迟一帧,那么默认的系统执行顺序(顺序不确定)会有更好的性能。偏重操作的游戏则要重视延迟问题,要考虑系统执行顺序。
显式系统排序
明确指定系统执行顺序:
fn main() { App::new() .add_plugins(DefaultPlugins) // 这些系统不关心执行顺序 .add_system(particle_effects) .add_system(npc_behaviors) .add_system(enemy_movement) .add_system(input_handling) .add_system( player_movement // player_movement 总是在 enemy_movement 之前执行 .before(enemy_movement) // player_movement 总是在 input_handling 之后执行 .after(input_handling) ) .run(); }
.before/.after 可以在一个系统上多次使用。
标签
标签是高级用法。标签可以是字符串(String),也可以是任何实现了 SystemLabel 的自定义类型。
可以在同一个系统上设置多个标签(.label、.before、.after),也可以在多个系统上设置同一个标签。
每个标签都是参考点,系统可以根据标签来排序。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum MyLabel { Input, Player, } fn main() { App::new() .add_plugins(DefaultPlugins) // 创建标签 .add_system(input_joystick.label(MyLabel::Input)) .add_system(input_keyboard.label(MyLabel::Input)) .add_system(input_touch.label(MyLabel::Input)) // 这个系统总是在被 input 标签标记的系统之前执行 .add_system(input_parameters.before(MyLabel::Input)) // 这个系统总是在被 input、map 标签标记的系统之后执行 // 同样加一些标签 .add_system( player_movement // 也可以用字符串作为标签 .label("player_movement") .label(MyLabel::Player) .label(MyLabel::Input) ) .run(); }
多个系统拥有共同的标签或顺序时,可以用 [System Sets]。
循环依赖
[TODO:看不懂] If you have multiple systems mutually depending on each other, then it is clearly impossible to resolve the situation completely like that.
You should try to redesign your game to avoid such situations, or just accept the consequences. You can at least make it behave predictably, using explicit ordering to specify the order you prefer.