From 155ebf7898bf0e0441bfdb27dd76fc59a5e11ba7 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 9 Jun 2025 13:03:02 -0700 Subject: [PATCH] Write real docs for `SystemSet` (#19538) # Objective `SystemSet`s are surprisingly rich and nuanced, but are extremely poorly documented. Fixes #19536. ## Solution Explain the basic concept of system sets, how to create them, and give some opinionated advice about their more advanced functionality. ## Follow-up I'd like proper module level docs on system ordering that I can link to here, but they don't exist. Punting to follow-up! --------- Co-authored-by: theotherphil --- crates/bevy_ecs/src/schedule/set.rs | 88 ++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/schedule/set.rs b/crates/bevy_ecs/src/schedule/set.rs index 4974be5d43..2243e5019f 100644 --- a/crates/bevy_ecs/src/schedule/set.rs +++ b/crates/bevy_ecs/src/schedule/set.rs @@ -60,7 +60,93 @@ define_label!( ); define_label!( - /// Types that identify logical groups of systems. + /// System sets are tag-like labels that can be used to group systems together. + /// + /// This allows you to share configuration (like run conditions) across multiple systems, + /// and order systems or system sets relative to conceptual groups of systems. + /// To control the behavior of a system set as a whole, use [`Schedule::configure_sets`](crate::prelude::Schedule::configure_sets), + /// or the method of the same name on `App`. + /// + /// Systems can belong to any number of system sets, reflecting multiple roles or facets that they might have. + /// For example, you may want to annotate a system as "consumes input" and "applies forces", + /// and ensure that your systems are ordered correctly for both of those sets. + /// + /// System sets can belong to any number of other system sets, + /// allowing you to create nested hierarchies of system sets to group systems together. + /// Configuration applied to system sets will flow down to their members (including other system sets), + /// allowing you to set and modify the configuration in a single place. + /// + /// Systems sets are also useful for exposing a consistent public API for dependencies + /// to hook into across versions of your crate, + /// allowing them to add systems to a specific set, or order relative to that set, + /// without leaking implementation details of the exact systems involved. + /// + /// ## Defining new system sets + /// + /// To create a new system set, use the `#[derive(SystemSet)]` macro. + /// Unit structs are a good choice for one-off sets. + /// + /// ```rust + /// # use bevy_ecs::prelude::*; + /// + /// #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] + /// struct PhysicsSystems; + /// ``` + /// + /// When you want to define several related system sets, + /// consider creating an enum system set. + /// Each variant will be treated as a separate system set. + /// + /// ```rust + /// # use bevy_ecs::prelude::*; + /// + /// #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] + /// enum CombatSystems { + /// TargetSelection, + /// DamageCalculation, + /// Cleanup, + /// } + /// ``` + /// + /// By convention, the listed order of the system set in the enum + /// corresponds to the order in which the systems are run. + /// Ordering must be explicitly added to ensure that this is the case, + /// but following this convention will help avoid confusion. + /// + /// ### Adding systems to system sets + /// + /// To add systems to a system set, call [`in_set`](crate::prelude::IntoScheduleConfigs::in_set) on the system function + /// while adding it to your app or schedule. + /// + /// Like usual, these methods can be chained with other configuration methods like [`before`](crate::prelude::IntoScheduleConfigs::before), + /// or repeated to add systems to multiple sets. + /// + /// ```rust + /// use bevy_ecs::prelude::*; + /// + /// #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] + /// enum CombatSystems { + /// TargetSelection, + /// DamageCalculation, + /// Cleanup, + /// } + /// + /// fn target_selection() {} + /// + /// fn enemy_damage_calculation() {} + /// + /// fn player_damage_calculation() {} + /// + /// let mut schedule = Schedule::default(); + /// // Configuring the sets to run in order. + /// schedule.configure_sets((CombatSystems::TargetSelection, CombatSystems::DamageCalculation, CombatSystems::Cleanup).chain()); + /// + /// // Adding a single system to a set. + /// schedule.add_systems(target_selection.in_set(CombatSystems::TargetSelection)); + /// + /// // Adding multiple systems to a set. + /// schedule.add_systems((player_damage_calculation, enemy_damage_calculation).in_set(CombatSystems::DamageCalculation)); + /// ``` #[diagnostic::on_unimplemented( note = "consider annotating `{Self}` with `#[derive(SystemSet)]`" )]