//! Shows how systems with a similar purpose can be grouped into sets. //! //! ```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 //! ``` //! //! The `Physics` label represents a [`SystemSet`] containing two systems. //! This set's criteria is to stop after a second has elapsed. //! The two systems (`update_velocity`, `movement`) run in a specified order. //! //! Another label `PostPhysics` uses run criteria to only run after `Physics` has finished. //! This set's criteria is to run only when _not done_, as specified via a resource. //! The two systems here (collision, sfx) are not specified to run in any order, and the actual //! ordering can then change between invocations. //! //! Lastly a system with run criteria _done_ is used to exit the app. use bevy::{app::AppExit, ecs::schedule::ShouldRun, prelude::*}; /// A [`SystemLabel`] can be applied as a label to systems and system sets, /// which can then be referred to from other systems. /// This is useful in case a user wants to e.g. run _before_ or _after_ /// some label. /// `Clone`, `Hash`, `Debug`, `PartialEq`, `Eq`, are all required to derive /// [`SystemLabel`]. #[derive(Clone, Hash, Debug, PartialEq, Eq, SystemLabel)] struct Physics; #[derive(Clone, Hash, Debug, PartialEq, Eq, SystemLabel)] struct PostPhysics; /// Resource used to stop our example. #[derive(Resource, Default)] struct Done(bool); fn main() { #[derive(RunCriteriaLabel)] struct IsDone; App::new() .add_plugins(DefaultPlugins) .init_resource::() // Note that the system sets added in this example set their run criteria explicitly. // See the `ecs/state.rs` example for a pattern where run criteria are set implicitly for common // use cases- typically state transitions. // Also note that a system set has a single run criterion at most, which means using `.with_run_criteria(...)` // after `SystemSet::on_update(...)` would override the state transition criterion. .add_system_set( SystemSet::new() // This label is added to all systems in this set. // The label can then be referred to elsewhere (other sets). .label(Physics) // This criteria ensures this whole system set only runs when this system's // output says so (ShouldRun::Yes) .with_run_criteria(run_for_a_second) .with_system(update_velocity) // Make movement run after update_velocity .with_system(movement.after(update_velocity)), ) .add_system_set( SystemSet::new() .label(PostPhysics) // This whole set runs after `Physics` (which in this case is a label for // another set). // There is also `.before(..)`. .after(Physics) // This shows that we can modify existing run criteria results. // 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(IsDone, inverse)) // `collision` and `sfx` are not ordered with respect to // each other, and may run in any order .with_system(collision) .with_system(sfx), ) .add_system( exit.after(PostPhysics) // Label the run criteria such that the `PostPhysics` set can reference it .with_run_criteria(is_done.label(IsDone)), ) .run(); } /// Example of a run criteria. /// Here we only want to run for a second, then stop. fn run_for_a_second(time: Res