pub struct Schedule { /* private fields */ }Expand description
A collection of systems, and the metadata and executor needed to run them in a certain order under certain conditions.
§Schedule labels
Each schedule has a ScheduleLabel value. This value is used to uniquely identify the
schedule when added to a World’s Schedules, and may be used to specify which schedule
a system should be added to.
§Example
Here is an example of a Schedule running a “Hello world” system:
fn hello_world() { println!("Hello world!") }
fn main() {
let mut world = World::new();
let mut schedule = Schedule::default();
schedule.add_systems(hello_world);
schedule.run(&mut world);
}A schedule can also run several systems in an ordered way:
fn system_one() { println!("System 1 works!") }
fn system_two() { println!("System 2 works!") }
fn system_three() { println!("System 3 works!") }
fn main() {
let mut world = World::new();
let mut schedule = Schedule::default();
schedule.add_systems((
system_two,
system_one.before(system_two),
system_three.after(system_two),
));
schedule.run(&mut world);
}Schedules are often inserted into a World and identified by their ScheduleLabel only:
use bevy_ecs::schedule::ScheduleLabel;
// Declare a new schedule label.
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash, Default)]
struct Update;
// This system shall be part of the schedule.
fn an_update_system() {
println!("Hello world!");
}
fn main() {
let mut world = World::new();
// Add a system to the schedule with that label (creating it automatically).
world.get_resource_or_init::<Schedules>().add_systems(Update, an_update_system);
// Run the schedule, and therefore run the system.
world.run_schedule(Update);
}Implementations§
Source§impl Schedule
impl Schedule
Sourcepub fn new(label: impl ScheduleLabel) -> Schedule
pub fn new(label: impl ScheduleLabel) -> Schedule
Constructs an empty Schedule.
Examples found in repository?
16fn main() {
17 let mut app = App::new();
18
19 // Create a new [`Schedule`]. For demonstration purposes, we configure it to use a single threaded executor so that
20 // systems in this schedule are never run in parallel. However, this is not a requirement for custom schedules in
21 // general.
22 let mut custom_update_schedule = Schedule::new(SingleThreadedUpdate);
23 custom_update_schedule.set_executor(SingleThreadedExecutor::new());
24
25 // Adding the schedule to the app does not automatically run the schedule. This merely registers the schedule so
26 // that systems can look it up using the `Schedules` resource.
27 app.add_schedule(custom_update_schedule);
28
29 // Bevy `App`s have a `main_schedule_label` field that configures which schedule is run by the App's `runner`.
30 // By default, this is `Main`. The `Main` schedule is responsible for running Bevy's main schedules such as
31 // `Update`, `Startup` or `Last`.
32 //
33 // We can configure the `Main` schedule to run our custom update schedule relative to the existing ones by modifying
34 // the `MainScheduleOrder` resource.
35 //
36 // Note that we modify `MainScheduleOrder` directly in `main` and not in a startup system. The reason for this is
37 // that the `MainScheduleOrder` cannot be modified from systems that are run as part of the `Main` schedule.
38 let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
39 main_schedule_order.insert_after(Update, SingleThreadedUpdate);
40
41 // Adding a custom startup schedule works similarly, but needs to use `insert_startup_after`
42 // instead of `insert_after`.
43 app.add_schedule(Schedule::new(CustomStartup));
44
45 let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
46 main_schedule_order.insert_startup_after(PreStartup, CustomStartup);
47
48 app.add_systems(SingleThreadedUpdate, single_threaded_update_system)
49 .add_systems(CustomStartup, custom_startup_system)
50 .add_systems(PreStartup, pre_startup_system)
51 .add_systems(Startup, startup_system)
52 .add_systems(First, first_system)
53 .add_systems(Update, update_system)
54 .add_systems(Last, last_system)
55 .run();
56}More examples
78fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
79 let mut rng = ChaCha8Rng::seed_from_u64(42);
80 let mut app = App::default();
81 let world = app.world_mut();
82
83 // register a bunch of components
84 let component_ids: Vec<ComponentId> = (1..=num_components)
85 .map(|i| {
86 world.register_component_with_descriptor(
87 // SAFETY:
88 // * We don't implement a drop function
89 // * u8 is Sync and Send
90 unsafe {
91 ComponentDescriptor::new_with_layout(
92 format!("Component{i}").to_string(),
93 StorageType::Table,
94 Layout::new::<u8>(),
95 None,
96 true, // is mutable
97 ComponentCloneBehavior::Default,
98 None,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.random_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .sample(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.random_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .sample(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.random_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 // overwrite Update schedule in the app
161 app.add_schedule(schedule);
162 app.add_plugins(MinimalPlugins)
163 .add_plugins(DiagnosticsPlugin)
164 .add_plugins(LogPlugin::default())
165 .add_plugins(FrameTimeDiagnosticsPlugin::default())
166 .add_plugins(LogDiagnosticsPlugin::filtered(HashSet::from_iter([
167 DiagnosticPath::new("fps"),
168 ])));
169 app.run();
170}Sourcepub fn is_changed(&self) -> bool
pub fn is_changed(&self) -> bool
Returns whether this schedule has been changed since the last time it was built.
Sourcepub fn label(&self) -> Interned<dyn ScheduleLabel>
pub fn label(&self) -> Interned<dyn ScheduleLabel>
Returns the InternedScheduleLabel for this Schedule,
corresponding to the ScheduleLabel this schedule was created with.
Examples found in repository?
91fn count_ambiguities(sub_app: &mut SubApp) -> AmbiguitiesCount {
92 let schedule_labels = sub_app
93 .world()
94 .resource::<Schedules>()
95 .iter()
96 .map(|(_, schedule)| schedule.label())
97 .collect::<Vec<_>>();
98 let mut ambiguities = <HashMap<_, _>>::default();
99 for label in schedule_labels {
100 let ambiguities_in_schedule =
101 sub_app
102 .world_mut()
103 .schedule_scope(label, |world, schedule| {
104 schedule.initialize(world).unwrap().unwrap();
105 schedule.graph().conflicting_systems().len()
106 });
107 ambiguities.insert(label, ambiguities_in_schedule);
108 }
109 AmbiguitiesCount(ambiguities)
110}Sourcepub fn add_systems<M>(
&mut self,
systems: impl IntoScheduleConfigs<Box<dyn System<Out = (), In = ()>>, M>,
) -> &mut Schedule
pub fn add_systems<M>( &mut self, systems: impl IntoScheduleConfigs<Box<dyn System<Out = (), In = ()>>, M>, ) -> &mut Schedule
Add a collection of systems to the schedule.
Examples found in repository?
45fn main() {
46 let mut world = World::new();
47 world.init_resource::<Counter>();
48
49 let mut schedule = Schedule::default();
50 schedule.set_executor(CustomExecutor);
51 schedule.add_systems((increment, print_counter).chain());
52
53 for _ in 0..5 {
54 schedule.run(&mut world);
55 }
56}More examples
78fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
79 let mut rng = ChaCha8Rng::seed_from_u64(42);
80 let mut app = App::default();
81 let world = app.world_mut();
82
83 // register a bunch of components
84 let component_ids: Vec<ComponentId> = (1..=num_components)
85 .map(|i| {
86 world.register_component_with_descriptor(
87 // SAFETY:
88 // * We don't implement a drop function
89 // * u8 is Sync and Send
90 unsafe {
91 ComponentDescriptor::new_with_layout(
92 format!("Component{i}").to_string(),
93 StorageType::Table,
94 Layout::new::<u8>(),
95 None,
96 true, // is mutable
97 ComponentCloneBehavior::Default,
98 None,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.random_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .sample(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.random_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .sample(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.random_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 // overwrite Update schedule in the app
161 app.add_schedule(schedule);
162 app.add_plugins(MinimalPlugins)
163 .add_plugins(DiagnosticsPlugin)
164 .add_plugins(LogPlugin::default())
165 .add_plugins(FrameTimeDiagnosticsPlugin::default())
166 .add_plugins(LogDiagnosticsPlugin::filtered(HashSet::from_iter([
167 DiagnosticPath::new("fps"),
168 ])));
169 app.run();
170}Sourcepub fn remove_systems_in_set<M>(
&mut self,
set: impl IntoSystemSet<M>,
world: &mut World,
policy: ScheduleCleanupPolicy,
) -> Result<usize, ScheduleError>
pub fn remove_systems_in_set<M>( &mut self, set: impl IntoSystemSet<M>, world: &mut World, policy: ScheduleCleanupPolicy, ) -> Result<usize, ScheduleError>
Removes all systems in a SystemSet. This will cause the schedule to be rebuilt when
the schedule is run again. A ScheduleError is returned if the schedule needs to be
Schedule::initialize’d or the set is not found.
Note that this can remove all systems of a type if you pass the system to this function as systems implicitly create a set based on the system type.
§Example
let mut schedule = Schedule::default();
// add the system to the schedule
schedule.add_systems(my_system);
let mut world = World::default();
// remove the system
schedule.remove_systems_in_set(my_system, &mut world, ScheduleCleanupPolicy::RemoveSystemsOnly);Sourcepub fn ignore_ambiguity<M1, M2, S1, S2>(
&mut self,
a: S1,
b: S2,
) -> &mut Schedulewhere
S1: IntoSystemSet<M1>,
S2: IntoSystemSet<M2>,
pub fn ignore_ambiguity<M1, M2, S1, S2>(
&mut self,
a: S1,
b: S2,
) -> &mut Schedulewhere
S1: IntoSystemSet<M1>,
S2: IntoSystemSet<M2>,
Suppress warnings and errors that would result from systems in these sets having ambiguities
(conflicting access but indeterminate order) with systems in set.
Sourcepub fn configure_sets<M>(
&mut self,
sets: impl IntoScheduleConfigs<Interned<dyn SystemSet>, M>,
) -> &mut Schedule
pub fn configure_sets<M>( &mut self, sets: impl IntoScheduleConfigs<Interned<dyn SystemSet>, M>, ) -> &mut Schedule
Configures a collection of system sets in this schedule, adding them if they does not exist.
Sourcepub fn add_build_pass<T>(&mut self, pass: T) -> &mut Schedulewhere
T: ScheduleBuildPass,
pub fn add_build_pass<T>(&mut self, pass: T) -> &mut Schedulewhere
T: ScheduleBuildPass,
Add a custom build pass to the schedule.
Sourcepub fn remove_build_pass<T>(&mut self)where
T: ScheduleBuildPass,
pub fn remove_build_pass<T>(&mut self)where
T: ScheduleBuildPass,
Remove a custom build pass.
Sourcepub fn set_build_settings(
&mut self,
settings: ScheduleBuildSettings,
) -> &mut Schedule
pub fn set_build_settings( &mut self, settings: ScheduleBuildSettings, ) -> &mut Schedule
Changes miscellaneous build settings.
If settings.auto_insert_apply_deferred
is false, this clears *_ignore_deferred edge settings configured so far.
Generally this method should be used before adding systems or set configurations to the schedule, not after.
Examples found in repository?
70fn configure_ambiguity_detection(sub_app: &mut SubApp) {
71 let mut schedules = sub_app.world_mut().resource_mut::<Schedules>();
72 for (_, schedule) in schedules.iter_mut() {
73 schedule.set_build_settings(ScheduleBuildSettings {
74 // NOTE: you can change this to `LogLevel::Ignore` to easily see the current number of ambiguities.
75 ambiguity_detection: LogLevel::Warn,
76 // With auto-inserted apply_deferred stages, these can cause two ambiguous systems to
77 // become accidentally ordered by one of the apply_deferred stages. Disabling requires
78 // us to meet a higher bar. We don't just want no ambiguities - we also don't want
79 // changes to systems or the auto-insert code from "creating" new ambiguities (by
80 // reordering the graph). However, the cost is that the graph is no longer runnable,
81 // since Bevy crates often rely on auto-insert apply_deferred to not panic (e.g.,
82 // because a resource wasn't inserted).
83 auto_insert_apply_deferred: false,
84 use_shortnames: false,
85 ..default()
86 });
87 }
88}More examples
20fn main() {
21 App::new()
22 // We can modify the reporting strategy for system execution order ambiguities on a per-schedule basis.
23 // You must do this for each schedule you want to inspect; child schedules executed within an inspected
24 // schedule do not inherit this modification.
25 .edit_schedule(Update, |schedule| {
26 schedule.set_build_settings(ScheduleBuildSettings {
27 ambiguity_detection: LogLevel::Warn,
28 ..default()
29 });
30 })
31 .init_resource::<A>()
32 .init_resource::<B>()
33 .add_systems(
34 Update,
35 (
36 // This pair of systems has an ambiguous order,
37 // as their data access conflicts, and there's no order between them.
38 reads_a,
39 writes_a,
40 // This pair of systems has conflicting data access,
41 // but it's resolved with an explicit ordering:
42 // the .after relationship here means that we will always double after adding.
43 adds_one_to_b,
44 doubles_b.after(adds_one_to_b),
45 // This system isn't ambiguous with adds_one_to_b,
46 // due to the transitive ordering created by our constraints:
47 // if A is before B is before C, then A must be before C as well.
48 reads_b.after(doubles_b),
49 // This system will conflict with all of our writing systems
50 // but we've silenced its ambiguity with adds_one_to_b.
51 // This should only be done in the case of clear false positives:
52 // leave a comment in your code justifying the decision!
53 reads_a_and_b.ambiguous_with(adds_one_to_b),
54 ),
55 )
56 // Be mindful, internal ambiguities are reported too!
57 // If there are any ambiguities due solely to DefaultPlugins,
58 // or between DefaultPlugins and any of your third party plugins,
59 // please file a bug with the repo responsible!
60 // Only *you* can prevent nondeterministic bugs due to greedy parallelism.
61 .add_plugins(DefaultPlugins)
62 .run();
63}Sourcepub fn get_build_settings(&self) -> ScheduleBuildSettings
pub fn get_build_settings(&self) -> ScheduleBuildSettings
Returns the schedule’s current ScheduleBuildSettings.
Sourcepub fn set_executor(
&mut self,
executor: impl SystemExecutor + 'static,
) -> &mut Schedule
pub fn set_executor( &mut self, executor: impl SystemExecutor + 'static, ) -> &mut Schedule
Replaces the schedule’s executor.
Examples found in repository?
45fn main() {
46 let mut world = World::new();
47 world.init_resource::<Counter>();
48
49 let mut schedule = Schedule::default();
50 schedule.set_executor(CustomExecutor);
51 schedule.add_systems((increment, print_counter).chain());
52
53 for _ in 0..5 {
54 schedule.run(&mut world);
55 }
56}More examples
16fn main() {
17 let mut app = App::new();
18
19 // Create a new [`Schedule`]. For demonstration purposes, we configure it to use a single threaded executor so that
20 // systems in this schedule are never run in parallel. However, this is not a requirement for custom schedules in
21 // general.
22 let mut custom_update_schedule = Schedule::new(SingleThreadedUpdate);
23 custom_update_schedule.set_executor(SingleThreadedExecutor::new());
24
25 // Adding the schedule to the app does not automatically run the schedule. This merely registers the schedule so
26 // that systems can look it up using the `Schedules` resource.
27 app.add_schedule(custom_update_schedule);
28
29 // Bevy `App`s have a `main_schedule_label` field that configures which schedule is run by the App's `runner`.
30 // By default, this is `Main`. The `Main` schedule is responsible for running Bevy's main schedules such as
31 // `Update`, `Startup` or `Last`.
32 //
33 // We can configure the `Main` schedule to run our custom update schedule relative to the existing ones by modifying
34 // the `MainScheduleOrder` resource.
35 //
36 // Note that we modify `MainScheduleOrder` directly in `main` and not in a startup system. The reason for this is
37 // that the `MainScheduleOrder` cannot be modified from systems that are run as part of the `Main` schedule.
38 let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
39 main_schedule_order.insert_after(Update, SingleThreadedUpdate);
40
41 // Adding a custom startup schedule works similarly, but needs to use `insert_startup_after`
42 // instead of `insert_after`.
43 app.add_schedule(Schedule::new(CustomStartup));
44
45 let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
46 main_schedule_order.insert_startup_after(PreStartup, CustomStartup);
47
48 app.add_systems(SingleThreadedUpdate, single_threaded_update_system)
49 .add_systems(CustomStartup, custom_startup_system)
50 .add_systems(PreStartup, pre_startup_system)
51 .add_systems(Startup, startup_system)
52 .add_systems(First, first_system)
53 .add_systems(Update, update_system)
54 .add_systems(Last, last_system)
55 .run();
56}Sourcepub fn set_apply_final_deferred(
&mut self,
apply_final_deferred: bool,
) -> &mut Schedule
pub fn set_apply_final_deferred( &mut self, apply_final_deferred: bool, ) -> &mut Schedule
Set whether the schedule applies deferred system buffers on final time or not. This is a catch-all
in case a system uses commands but was not explicitly ordered before an instance of
ApplyDeferred. By default this
setting is true, but may be disabled if needed.
Sourcepub fn run(&mut self, world: &mut World)
pub fn run(&mut self, world: &mut World)
Runs all systems in this schedule on the world, using its current execution strategy.
Examples found in repository?
45fn main() {
46 let mut world = World::new();
47 world.init_resource::<Counter>();
48
49 let mut schedule = Schedule::default();
50 schedule.set_executor(CustomExecutor);
51 schedule.add_systems((increment, print_counter).chain());
52
53 for _ in 0..5 {
54 schedule.run(&mut world);
55 }
56}Sourcepub fn initialize(
&mut self,
world: &mut World,
) -> Result<Option<ScheduleBuildMetadata>, ScheduleBuildError>
pub fn initialize( &mut self, world: &mut World, ) -> Result<Option<ScheduleBuildMetadata>, ScheduleBuildError>
Initializes any newly-added systems and conditions, rebuilds the executable schedule, and re-initializes the executor.
Moves all systems and run conditions out of the ScheduleGraph. If the schedule is built
successfully, returns Some with the metadata. If the schedule has previously been built
successfully, returns None.
Examples found in repository?
91fn count_ambiguities(sub_app: &mut SubApp) -> AmbiguitiesCount {
92 let schedule_labels = sub_app
93 .world()
94 .resource::<Schedules>()
95 .iter()
96 .map(|(_, schedule)| schedule.label())
97 .collect::<Vec<_>>();
98 let mut ambiguities = <HashMap<_, _>>::default();
99 for label in schedule_labels {
100 let ambiguities_in_schedule =
101 sub_app
102 .world_mut()
103 .schedule_scope(label, |world, schedule| {
104 schedule.initialize(world).unwrap().unwrap();
105 schedule.graph().conflicting_systems().len()
106 });
107 ambiguities.insert(label, ambiguities_in_schedule);
108 }
109 AmbiguitiesCount(ambiguities)
110}Sourcepub fn graph(&self) -> &ScheduleGraph
pub fn graph(&self) -> &ScheduleGraph
Returns the ScheduleGraph.
Examples found in repository?
91fn count_ambiguities(sub_app: &mut SubApp) -> AmbiguitiesCount {
92 let schedule_labels = sub_app
93 .world()
94 .resource::<Schedules>()
95 .iter()
96 .map(|(_, schedule)| schedule.label())
97 .collect::<Vec<_>>();
98 let mut ambiguities = <HashMap<_, _>>::default();
99 for label in schedule_labels {
100 let ambiguities_in_schedule =
101 sub_app
102 .world_mut()
103 .schedule_scope(label, |world, schedule| {
104 schedule.initialize(world).unwrap().unwrap();
105 schedule.graph().conflicting_systems().len()
106 });
107 ambiguities.insert(label, ambiguities_in_schedule);
108 }
109 AmbiguitiesCount(ambiguities)
110}Sourcepub fn graph_mut(&mut self) -> &mut ScheduleGraph
pub fn graph_mut(&mut self) -> &mut ScheduleGraph
Returns a mutable reference to the ScheduleGraph.
Sourcepub fn check_change_ticks(&mut self, check: CheckChangeTicks)
pub fn check_change_ticks(&mut self, check: CheckChangeTicks)
Iterates the change ticks of all systems in the schedule and clamps any older than
MAX_CHANGE_AGE.
This prevents overflow and thus prevents false positives.
Sourcepub fn apply_deferred(&mut self, world: &mut World)
pub fn apply_deferred(&mut self, world: &mut World)
Directly applies any accumulated Deferred system parameters (like Commands) to the world.
Like always, deferred system parameters are applied in the “topological sort order” of the schedule graph. As a result, buffers from one system are only guaranteed to be applied before those of other systems if there is an explicit system ordering between the two systems.
This is used in rendering to extract data from the main world, storing the data in system buffers, before applying their buffers in a different world.
Sourcepub fn systems(
&self,
) -> Result<impl Iterator<Item = (SystemKey, &Box<dyn System<Out = (), In = ()>>)>, ScheduleNotInitialized>
pub fn systems( &self, ) -> Result<impl Iterator<Item = (SystemKey, &Box<dyn System<Out = (), In = ()>>)>, ScheduleNotInitialized>
Returns an iterator over all systems in this schedule.
Note: this method will return ScheduleNotInitialized if the
schedule has never been initialized or run.
Examples found in repository?
99fn build_ui(
100 mut commands: Commands,
101 asset_server: Res<AssetServer>,
102 schedules: Res<Schedules>,
103 mut stepping: ResMut<Stepping>,
104 mut state: ResMut<State>,
105) {
106 let mut text_spans = Vec::new();
107 let mut always_run: Vec<(
108 bevy_ecs::intern::Interned<dyn ScheduleLabel + 'static>,
109 NodeId,
110 )> = Vec::new();
111
112 let Ok(schedule_order) = stepping.schedules() else {
113 return;
114 };
115
116 // go through the stepping schedules and construct a list of systems for
117 // each label
118 for label in schedule_order {
119 let schedule = schedules.get(*label).unwrap();
120 text_spans.push((
121 TextSpan(format!("{label:?}\n")),
122 TextFont {
123 font: asset_server.load(FONT_BOLD).into(),
124 ..default()
125 },
126 TextColor(FONT_COLOR),
127 ));
128
129 // grab the list of systems in the schedule, in the order the
130 // single-threaded executor would run them.
131 let Ok(systems) = schedule.systems() else {
132 return;
133 };
134
135 for (key, system) in systems {
136 // skip bevy default systems; we don't want to step those
137 #[cfg(feature = "debug")]
138 if system.name().as_string().starts_with("bevy") {
139 always_run.push((*label, NodeId::System(key)));
140 continue;
141 }
142
143 // Add an entry to our systems list so we can find where to draw
144 // the cursor when the stepping cursor is at this system
145 // we add plus 1 to account for the empty root span
146 state
147 .systems
148 .push((*label, NodeId::System(key), text_spans.len() + 1));
149
150 // Add a text section for displaying the cursor for this system
151 text_spans.push((
152 TextSpan::new(" "),
153 TextFont::default(),
154 TextColor(FONT_COLOR),
155 ));
156
157 // add the name of the system to the ui
158 text_spans.push((
159 TextSpan(format!("{}\n", system.name())),
160 TextFont::default(),
161 TextColor(FONT_COLOR),
162 ));
163 }
164 }
165
166 for (label, node) in always_run.drain(..) {
167 stepping.always_run_node(label, node);
168 }
169
170 commands.spawn((
171 Text::default(),
172 SteppingUi,
173 Node {
174 position_type: PositionType::Absolute,
175 top: state.ui_top,
176 left: state.ui_left,
177 padding: UiRect::all(px(10)),
178 ..default()
179 },
180 BackgroundColor(Color::srgba(1.0, 1.0, 1.0, 0.33)),
181 Visibility::Hidden,
182 Children::spawn(text_spans),
183 ));
184}Sourcepub fn systems_len(&self) -> usize
pub fn systems_len(&self) -> usize
Returns the number of systems in this schedule.
Trait Implementations§
Source§impl Default for Schedule
impl Default for Schedule
Source§fn default() -> Schedule
fn default() -> Schedule
Creates a schedule with a default label. Only use in situations where
you don’t care about the ScheduleLabel. Inserting a default schedule
into the world risks overwriting another schedule. For most situations
you should use Schedule::new.
Auto Trait Implementations§
impl !RefUnwindSafe for Schedule
impl !UnwindSafe for Schedule
impl Freeze for Schedule
impl Send for Schedule
impl Sync for Schedule
impl Unpin for Schedule
impl UnsafeUnpin for Schedule
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ConditionalSend for Twhere
T: Send,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.