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.
§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);
}
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?
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
let mut app = App::new();
// Create a new [`Schedule`]. For demonstration purposes, we configure it to use a single threaded executor so that
// systems in this schedule are never run in parallel. However, this is not a requirement for custom schedules in
// general.
let mut custom_update_schedule = Schedule::new(SingleThreadedUpdate);
custom_update_schedule.set_executor_kind(ExecutorKind::SingleThreaded);
// Adding the schedule to the app does not automatically run the schedule. This merely registers the schedule so
// that systems can look it up using the `Schedules` resource.
app.add_schedule(custom_update_schedule);
// Bevy `App`s have a `main_schedule_label` field that configures which schedule is run by the App's `runner`.
// By default, this is `Main`. The `Main` schedule is responsible for running Bevy's main schedules such as
// `Update`, `Startup` or `Last`.
//
// We can configure the `Main` schedule to run our custom update schedule relative to the existing ones by modifying
// the `MainScheduleOrder` resource.
//
// Note that we modify `MainScheduleOrder` directly in `main` and not in a startup system. The reason for this is
// that the `MainScheduleOrder` cannot be modified from systems that are run as part of the `Main` schedule.
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
main_schedule_order.insert_after(Update, SingleThreadedUpdate);
// Adding a custom startup schedule works similarly, but needs to use `insert_startup_after`
// instead of `insert_after`.
app.add_schedule(Schedule::new(CustomStartup));
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
main_schedule_order.insert_startup_after(PreStartup, CustomStartup);
app.add_systems(SingleThreadedUpdate, single_threaded_update_system)
.add_systems(CustomStartup, custom_startup_system)
.add_systems(PreStartup, pre_startup_system)
.add_systems(Startup, startup_system)
.add_systems(First, first_system)
.add_systems(Update, update_system)
.add_systems(Last, last_system)
.run();
}
sourcepub fn label(&self) -> Interned<dyn ScheduleLabel>
pub fn label(&self) -> Interned<dyn ScheduleLabel>
Get the InternedScheduleLabel
for this Schedule
.
sourcepub fn add_systems<M>(
&mut self,
systems: impl IntoSystemConfigs<M>
) -> &mut Schedule
pub fn add_systems<M>( &mut self, systems: impl IntoSystemConfigs<M> ) -> &mut Schedule
Add a collection of systems to the schedule.
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(
&mut self,
sets: impl IntoSystemSetConfigs
) -> &mut Schedule
pub fn configure_sets( &mut self, sets: impl IntoSystemSetConfigs ) -> &mut Schedule
Configures a collection of system sets in this schedule, adding them if they does not exist.
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.
Examples found in repository?
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
fn main() {
App::new()
// We can modify the reporting strategy for system execution order ambiguities on a per-schedule basis.
// You must do this for each schedule you want to inspect; child schedules executed within an inspected
// schedule do not inherit this modification.
.edit_schedule(Update, |schedule| {
schedule.set_build_settings(ScheduleBuildSettings {
ambiguity_detection: LogLevel::Warn,
..default()
});
})
.init_resource::<A>()
.init_resource::<B>()
.add_systems(
Update,
(
// This pair of systems has an ambiguous order,
// as their data access conflicts, and there's no order between them.
reads_a,
writes_a,
// This pair of systems has conflicting data access,
// but it's resolved with an explicit ordering:
// the .after relationship here means that we will always double after adding.
adds_one_to_b,
doubles_b.after(adds_one_to_b),
// This system isn't ambiguous with adds_one_to_b,
// due to the transitive ordering created by our constraints:
// if A is before B is before C, then A must be before C as well.
reads_b.after(doubles_b),
// This system will conflict with all of our writing systems
// but we've silenced its ambiguity with adds_one_to_b.
// This should only be done in the case of clear false positives:
// leave a comment in your code justifying the decision!
reads_a_and_b.ambiguous_with(adds_one_to_b),
),
)
// Be mindful, internal ambiguities are reported too!
// If there are any ambiguities due solely to DefaultPlugins,
// or between DefaultPlugins and any of your third party plugins,
// please file a bug with the repo responsible!
// Only *you* can prevent nondeterministic bugs due to greedy parallelism.
.add_plugins(DefaultPlugins)
.run();
}
sourcepub fn get_build_settings(&self) -> ScheduleBuildSettings
pub fn get_build_settings(&self) -> ScheduleBuildSettings
Returns the schedule’s current ScheduleBuildSettings
.
sourcepub fn get_executor_kind(&self) -> ExecutorKind
pub fn get_executor_kind(&self) -> ExecutorKind
Returns the schedule’s current execution strategy.
sourcepub fn set_executor_kind(&mut self, executor: ExecutorKind) -> &mut Schedule
pub fn set_executor_kind(&mut self, executor: ExecutorKind) -> &mut Schedule
Sets the schedule’s execution strategy.
Examples found in repository?
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
let mut app = App::new();
// Create a new [`Schedule`]. For demonstration purposes, we configure it to use a single threaded executor so that
// systems in this schedule are never run in parallel. However, this is not a requirement for custom schedules in
// general.
let mut custom_update_schedule = Schedule::new(SingleThreadedUpdate);
custom_update_schedule.set_executor_kind(ExecutorKind::SingleThreaded);
// Adding the schedule to the app does not automatically run the schedule. This merely registers the schedule so
// that systems can look it up using the `Schedules` resource.
app.add_schedule(custom_update_schedule);
// Bevy `App`s have a `main_schedule_label` field that configures which schedule is run by the App's `runner`.
// By default, this is `Main`. The `Main` schedule is responsible for running Bevy's main schedules such as
// `Update`, `Startup` or `Last`.
//
// We can configure the `Main` schedule to run our custom update schedule relative to the existing ones by modifying
// the `MainScheduleOrder` resource.
//
// Note that we modify `MainScheduleOrder` directly in `main` and not in a startup system. The reason for this is
// that the `MainScheduleOrder` cannot be modified from systems that are run as part of the `Main` schedule.
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
main_schedule_order.insert_after(Update, SingleThreadedUpdate);
// Adding a custom startup schedule works similarly, but needs to use `insert_startup_after`
// instead of `insert_after`.
app.add_schedule(Schedule::new(CustomStartup));
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
main_schedule_order.insert_startup_after(PreStartup, CustomStartup);
app.add_systems(SingleThreadedUpdate, single_threaded_update_system)
.add_systems(CustomStartup, custom_startup_system)
.add_systems(PreStartup, pre_startup_system)
.add_systems(Startup, startup_system)
.add_systems(First, first_system)
.add_systems(Update, update_system)
.add_systems(Last, last_system)
.run();
}
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
apply_deferred
. 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.
sourcepub fn initialize(
&mut self,
world: &mut World
) -> Result<(), ScheduleBuildError>
pub fn initialize( &mut self, world: &mut World ) -> Result<(), 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
.
sourcepub fn graph(&self) -> &ScheduleGraph
pub fn graph(&self) -> &ScheduleGraph
Returns the ScheduleGraph
.
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 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 = (NodeId, &Box<dyn System<In = (), Out = ()>>)>, ScheduleNotInitialized>
pub fn systems( &self ) -> Result<impl Iterator<Item = (NodeId, &Box<dyn System<In = (), Out = ()>>)>, 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?
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
fn build_ui(
mut commands: Commands,
asset_server: Res<AssetServer>,
schedules: Res<Schedules>,
mut stepping: ResMut<Stepping>,
mut state: ResMut<State>,
) {
let mut text_sections = Vec::new();
let mut always_run = Vec::new();
let Ok(schedule_order) = stepping.schedules() else {
return;
};
// go through the stepping schedules and construct a list of systems for
// each label
for label in schedule_order {
let schedule = schedules.get(*label).unwrap();
text_sections.push(TextSection::new(
format!("{:?}\n", label),
TextStyle {
font: asset_server.load(FONT_BOLD),
font_size: FONT_SIZE,
color: FONT_COLOR,
},
));
// grab the list of systems in the schedule, in the order the
// single-threaded executor would run them.
let Ok(systems) = schedule.systems() else {
return;
};
for (node_id, system) in systems {
// skip bevy default systems; we don't want to step those
if system.name().starts_with("bevy") {
always_run.push((*label, node_id));
continue;
}
// Add an entry to our systems list so we can find where to draw
// the cursor when the stepping cursor is at this system
state.systems.push((*label, node_id, text_sections.len()));
// Add a text section for displaying the cursor for this system
text_sections.push(TextSection::new(
" ",
TextStyle {
font: asset_server.load(FONT_MEDIUM),
font_size: FONT_SIZE,
color: FONT_COLOR,
},
));
// add the name of the system to the ui
text_sections.push(TextSection::new(
format!("{}\n", system.name()),
TextStyle {
font: asset_server.load(FONT_MEDIUM),
font_size: FONT_SIZE,
color: FONT_COLOR,
},
));
}
}
for (label, node) in always_run.drain(..) {
stepping.always_run_node(label, node);
}
commands.spawn((
SteppingUi,
TextBundle {
text: Text::from_sections(text_sections),
style: Style {
position_type: PositionType::Absolute,
top: state.ui_top,
left: state.ui_left,
padding: UiRect::all(Val::Px(10.0)),
..default()
},
background_color: BackgroundColor(Color::rgba(1.0, 1.0, 1.0, 0.33)),
visibility: Visibility::Hidden,
..default()
},
));
}
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 Freeze for Schedule
impl !RefUnwindSafe for Schedule
impl Send for Schedule
impl Sync for Schedule
impl Unpin for Schedule
impl !UnwindSafe 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<Image>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> 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
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> DowncastSync for T
impl<T> DowncastSync for T
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
Self
using data from the given World
.