Latest commit fbab01a
use bevy::app::AppExit; use bevy::ecs::schedule::ShouldRun; use bevy::prelude::*; /// 演示`SystemSet`如何搭配运行准则来使用 /// [`SystemLabel`]可以作为一个标签应用于系统和系统集,然后可以从其他系统中引用 /// TODO:This is useful in case a user wants to e.g. run _before_ or _after_ some label /// 派生[`SystemLabel`]时,需要同时派生`Clone`、`Hash`、`Debug`、`PartialEq`、`Eq` #[derive(Clone, Hash, Debug, PartialEq, Eq, SystemLabel)] struct Physics; #[derive(Clone, Hash, Debug, PartialEq, Eq, SystemLabel)] struct PostPhysics; // 用这个资源来停止此示例 #[derive(Default)] struct Done(bool); /// 这个用来说明:在[`SystemSet']中,单个系统也可以被标记,允许进一步微调运行顺序 #[derive(Clone, Hash, Debug, PartialEq, Eq, SystemLabel)] enum PhysicsSystem { UpdateVelocity, Movement, } /// 这个例子实现了以下方案: /// /// ```none /// Physics (Criteria: App has run < 1.0 seconds) /// \--> update_velocity (via label PhysicsSystem::UpdateVelocity) /// \--> movement (via label PhysicsSystem::Movement) /// PostPhysics (Criteria: Resource `done` is false) /// \--> collision || sfx /// Exit (Criteria: Resource `done` is true) /// \--> exit /// ``` /// /// `Physics`是一个包含两个系统的[`SystemSet`], /// `Physics`的运行准则是“经过2秒后停止”, /// `Physics`中的两个系统(`update_velocity`、`movement`)按指定顺序运行 /// /// `PostPhysics`的运行准则是“`Physics`完成后才开始运行”, /// `PostPhysics`的条件是由“Done”资源确定的,在“false”时运行,“true”时停止 /// `PostPhysics`中的两个系统(`collision`、`sfx`)没有指定运行顺序 /// /// 最后,根据“Done”资源来确认要退出应用程序 fn main() { App::new() .add_plugins(DefaultPlugins) .init_resource::<Done>() // 请注意,本例中添加的系统集明确设置了运行准则 // TODO:See the `ecs/state.rs` example for a pattern where run criteria are set implicitly for common use cases- typically state transitions. // 一个系统集最多有一个运行准则,这意味着: // 执行`SystemSet::on_update(...)`之后再执行`.with_run_criteria(...)`,会覆盖状态过度准则 .add_system_set( SystemSet::new() // 系统集内所有系统都会添加这个标签 // 这个标签可以在其他所有地方引用,包括其他系统集 .label(Physics) // 这个准则的作用:仅当"运行一秒"系统的输出为`ShouldRun::Yes`时,当前系统集才会运行 .with_run_criteria(运行一秒) .with_system( 更新速度 // 这个标签只添加给`更新速度`系统 .label(PhysicsSystem::UpdateVelocity), ) .with_system( 移动 // 只添加给`移动`系统 .label(PhysicsSystem::Movement) // 明确地指定执行顺序 .after(PhysicsSystem::UpdateVelocity), ), ) .add_system_set( SystemSet::new() .label(PostPhysics) // 这个系统集在`Physics`后面运行 // 与`.after(..)`类似的有`.before(..)` .after(Physics) // 可以修改现有的运行准则结果 // 这一步的目的是:TODO:Here we create a _not done_ criteria by piping the output of the `is_done` system and inverting the output. // 字符串也可以作为标签使用 .with_run_criteria(RunCriteria::pipe("已完成", 反转.system())) // `collision`和`sfx`没有明确指定顺序,因此运行时两个系统的顺序不确定 .with_system(碰撞) .with_system(sfx), ) .add_system( 退出.after(PostPhysics) .with_run_criteria(已完成.label("已完成")), ) .run(); } /// 运行准则的示例 /// 仅仅运行1秒,然后停止 fn 运行一秒( time: Res<Time>, mut done: ResMut<Done>, ) -> ShouldRun { let elapsed = time.seconds_since_startup(); if elapsed < 1.0 { info!( "应该再次运行。经过时间/剩余时间:{:.2}秒/{:.2}秒", elapsed, 1.0 - elapsed, ); ShouldRun::Yes } else { done.0 = true; ShouldRun::No } } /// 另一个运行准则,只用了一个资源 fn 已完成(done: Res<Done>) -> ShouldRun { if done.0 { ShouldRun::Yes } else { ShouldRun::No } } /// 与[`RunCriteria::pipe`]一起使用,把传递过去的系统反转 fn 反转(input: In<ShouldRun>) -> ShouldRun { match input.0 { ShouldRun::No => ShouldRun::Yes, ShouldRun::Yes => ShouldRun::No, _ => unreachable!(), } } fn 更新速度() { info!("正在更新速度"); } fn 移动() { info!("正在更新移动"); } fn 碰撞() { info!("完成“Physics”,正在检查碰撞"); } fn sfx() { info!("Physics已完成,播放一些sfx"); } fn 退出(mut app_exit_events: EventWriter<AppExit>) { info!("正在退出..."); app_exit_events.send(AppExit); }