pub trait IntoSystemConfigs<Marker>: Sized {
// Required method
fn into_configs(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>;
// Provided methods
fn in_set(
self,
set: impl SystemSet,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn before<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn after<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn before_ignore_deferred<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn after_ignore_deferred<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn distributive_run_if<M>(
self,
condition: impl Condition<M> + Clone,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn run_if<M>(
self,
condition: impl Condition<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn ambiguous_with<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn ambiguous_with_all(
self,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn chain(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
fn chain_ignore_deferred(
self,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>> { ... }
}
Expand description
Types that can convert into a SystemConfigs
.
This trait is implemented for “systems” (functions whose arguments all implement
SystemParam
), or tuples thereof.
It is a common entry point for system configurations.
§Examples
fn handle_input() {}
fn update_camera() {}
fn update_character() {}
app.add_systems(
Update,
(
handle_input,
(update_camera, update_character).after(handle_input)
)
);
Required Methods§
Sourcefn into_configs(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn into_configs(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Convert into a SystemConfigs
.
Provided Methods§
Sourcefn in_set(
self,
set: impl SystemSet,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn in_set( self, set: impl SystemSet, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Add these systems to the provided set
.
Examples found in repository?
More examples
95 96 97 98 99 100 101 102 103 104 105 106 107
fn build(&self, app: &mut App) {
app.add_plugins(ExtractComponentPlugin::<InstanceMaterialData>::default());
app.sub_app_mut(RenderApp)
.add_render_command::<Transparent3d, DrawCustom>()
.init_resource::<SpecializedMeshPipelines<CustomPipeline>>()
.add_systems(
Render,
(
queue_custom.in_set(RenderSet::QueueMeshes),
prepare_instance_buffers.in_set(RenderSet::PrepareResources),
),
);
}
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
fn finish(&self, app: &mut App) {
let render_app = app.sub_app_mut(RenderApp);
render_app.init_resource::<ComputePipeline>().add_systems(
Render,
prepare_bind_group
.in_set(RenderSet::PrepareBindGroups)
// We don't need to recreate the bind group every frame
.run_if(not(resource_exists::<GpuBufferBindGroup>)),
);
// Add the compute node as a top level node to the render graph
// This means it will only execute once per frame
render_app
.world_mut()
.resource_mut::<RenderGraph>()
.add_node(ComputeNodeLabel, ComputeNode::default());
}
101 102 103 104 105 106 107 108 109 110 111 112 113 114
fn build(&self, app: &mut App) {
// Extract the game of life image resource from the main world into the render world
// for operation on by the compute shader and display on the sprite.
app.add_plugins(ExtractResourcePlugin::<GameOfLifeImages>::default());
let render_app = app.sub_app_mut(RenderApp);
render_app.add_systems(
Render,
prepare_bind_group.in_set(RenderSet::PrepareBindGroups),
);
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
}
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
fn build(&self, app: &mut App) {
// Load our custom shader
let mut shaders = app.world_mut().resource_mut::<Assets<Shader>>();
shaders.insert(
&COLORED_MESH2D_SHADER_HANDLE,
Shader::from_wgsl(COLORED_MESH2D_SHADER, file!()),
);
// Register our custom draw function, and add our render systems
app.get_sub_app_mut(RenderApp)
.unwrap()
.add_render_command::<Transparent2d, DrawColoredMesh2d>()
.init_resource::<SpecializedRenderPipelines<ColoredMesh2dPipeline>>()
.init_resource::<RenderColoredMesh2dInstances>()
.add_systems(
ExtractSchedule,
extract_colored_mesh2d.after(extract_mesh2d),
)
.add_systems(Render, queue_colored_mesh2d.in_set(RenderSet::QueueMeshes));
}
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins)
.add_plugins(ExtractComponentPlugin::<CustomRenderedEntity>::default())
.add_systems(Startup, setup)
// Make sure to tell Bevy to check our entity for visibility. Bevy won't
// do this by default, for efficiency reasons.
.add_systems(
PostUpdate,
view::check_visibility::<WithCustomRenderedEntity>
.in_set(VisibilitySystems::CheckVisibility),
);
// We make sure to add these to the render app, not the main app.
app.get_sub_app_mut(RenderApp)
.unwrap()
.init_resource::<CustomPhasePipeline>()
.init_resource::<SpecializedRenderPipelines<CustomPhasePipeline>>()
.add_render_command::<Opaque3d, DrawCustomPhaseItemCommands>()
.add_systems(
Render,
prepare_custom_phase_item_buffers.in_set(RenderSet::Prepare),
)
.add_systems(Render, queue_custom_phase_item.in_set(RenderSet::Queue));
app.run();
}
Sourcefn before<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn before<M>( self, set: impl IntoSystemSet<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Runs before all systems in set
. If self
has any systems that produce Commands
or other Deferred
operations, all systems in set
will see their effect.
If automatically inserting apply_deferred
like
this isn’t desired, use before_ignore_deferred
instead.
Calling .chain
is often more convenient and ensures that all systems are added to the schedule.
Please check the caveats section of .after
for details.
Sourcefn after<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn after<M>( self, set: impl IntoSystemSet<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Run after all systems in set
. If set
has any systems that produce Commands
or other Deferred
operations, all systems in self
will see their effect.
If automatically inserting apply_deferred
like
this isn’t desired, use after_ignore_deferred
instead.
Calling .chain
is often more convenient and ensures that all systems are added to the schedule.
§Caveats
If you configure two System
s like (GameSystem::A).after(GameSystem::B)
or (GameSystem::A).before(GameSystem::B)
, the GameSystem::B
will not be automatically scheduled.
This means that the system GameSystem::A
and the system or systems in GameSystem::B
will run independently of each other if GameSystem::B
was never explicitly scheduled with configure_sets
If that is the case, .after
/.before
will not provide the desired behavior
and the systems can run in parallel or in any order determined by the scheduler.
Only use after(GameSystem::B)
and before(GameSystem::B)
when you know that B
has already been scheduled for you,
e.g. when it was provided by Bevy or a third-party dependency,
or you manually scheduled it somewhere else in your app.
Another caveat is that if GameSystem::B
is placed in a different schedule than GameSystem::A
,
any ordering calls between them—whether using .before
, .after
, or .chain
—will be silently ignored.
Examples found in repository?
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CameraControllerPlugin)
.add_systems(Startup, setup)
.add_systems(
Update,
(
cycle_cubemap_asset,
asset_loaded.after(cycle_cubemap_asset),
animate_light_direction,
),
)
.run();
}
More examples
16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(
Startup,
(
setup_ui,
setup_with_commands,
setup_with_world.after(setup_ui), // since we run `system_b` once in world it needs to run after `setup_ui`
),
)
.add_systems(Update, (trigger_system, evaluate_callbacks).chain())
.run();
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(TargetScale {
start_scale: 1.0,
target_scale: 1.0,
target_time: Timer::new(Duration::from_millis(SCALE_TIME), TimerMode::Once),
})
.add_systems(Startup, setup)
.add_systems(
Update,
(change_scaling, apply_scaling.after(change_scaling)),
)
.run();
}
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
fn main() {
// Create the app.
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<AppStatus>()
.init_resource::<Cubemaps>()
.add_systems(Startup, setup)
.add_systems(PreUpdate, add_environment_map_to_camera)
.add_systems(Update, change_reflection_type)
.add_systems(Update, toggle_rotation)
.add_systems(
Update,
rotate_camera
.after(toggle_rotation)
.after(change_reflection_type),
)
.add_systems(Update, update_text.after(rotate_camera))
.run();
}
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
fn main() {
App::new()
.init_resource::<AppSettings>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Chromatic Aberration Example".into(),
..default()
}),
..default()
}))
.add_systems(Startup, setup)
.add_systems(Update, handle_keyboard_input)
.add_systems(
Update,
(update_chromatic_aberration_settings, update_help_text)
.run_if(resource_changed::<AppSettings>)
.after(handle_keyboard_input),
)
.run();
}
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
fn build(&self, app: &mut App) {
let (s, r) = crossbeam_channel::unbounded();
let render_app = app
.insert_resource(MainWorldReceiver(r))
.sub_app_mut(RenderApp);
let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
graph.add_node(ImageCopy, ImageCopyDriver);
graph.add_node_edge(bevy::render::graph::CameraDriverLabel, ImageCopy);
render_app
.insert_resource(RenderWorldSender(s))
// Make ImageCopiers accessible in RenderWorld system and plugin
.add_systems(ExtractSchedule, image_copy_extract)
// Receives image data from buffer to channel
// so we need to run it after the render graph is done
.add_systems(Render, receive_image_from_buffer.after(RenderSet::Render));
}
- examples/2d/mesh2d_manual.rs
- examples/3d/pcss.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/stress_tests/many_sprites.rs
- examples/games/desk_toy.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/irradiance_volumes.rs
- examples/ecs/nondeterministic_system_order.rs
- examples/ecs/ecs_guide.rs
- examples/ecs/system_stepping.rs
Sourcefn before_ignore_deferred<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn before_ignore_deferred<M>( self, set: impl IntoSystemSet<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Run before all systems in set
.
Unlike before
, this will not cause the systems in
set
to wait for the deferred effects of self
to be applied.
Sourcefn after_ignore_deferred<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn after_ignore_deferred<M>( self, set: impl IntoSystemSet<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Run after all systems in set
.
Unlike after
, this will not wait for the deferred
effects of systems in set
to be applied.
Sourcefn distributive_run_if<M>(
self,
condition: impl Condition<M> + Clone,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn distributive_run_if<M>( self, condition: impl Condition<M> + Clone, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Add a run condition to each contained system.
Each system will receive its own clone of the Condition
and will only run
if the Condition
is true.
Each individual condition will be evaluated at most once (per schedule run), right before the corresponding system prepares to run.
This is equivalent to calling run_if
on each individual
system, as shown below:
schedule.add_systems((a, b).distributive_run_if(condition));
schedule.add_systems((a.run_if(condition), b.run_if(condition)));
§Note
Because the conditions are evaluated separately for each system, there is no guarantee that all evaluations in a single schedule run will yield the same result. If another system is run inbetween two evaluations it could cause the result of the condition to change.
Use run_if
on a SystemSet
if you want to make sure
that either all or none of the systems are run, or you don’t want to evaluate the run
condition for each contained system separately.
Sourcefn run_if<M>(
self,
condition: impl Condition<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn run_if<M>( self, condition: impl Condition<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Run the systems only if the Condition
is true
.
The Condition
will be evaluated at most once (per schedule run),
the first time a system in this set prepares to run.
If this set contains more than one system, calling run_if
is equivalent to adding each
system to a common set and configuring the run condition on that set, as shown below:
§Examples
schedule.add_systems((a, b).run_if(condition));
schedule.add_systems((a, b).in_set(C)).configure_sets(C.run_if(condition));
§Note
Because the condition will only be evaluated once, there is no guarantee that the condition is upheld after the first system has run. You need to make sure that no other systems that could invalidate the condition are scheduled inbetween the first and last run system.
Use distributive_run_if
if you want the
condition to be evaluated for each individual system, right before one is run.
Examples found in repository?
11 12 13 14 15 16 17 18 19 20 21 22 23
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
FrameTimeDiagnosticsPlugin,
LogDiagnosticsPlugin::default(),
))
.add_systems(
Update,
toggle.run_if(on_timer(Duration::from_secs_f32(10.0))),
)
.run();
}
More examples
10 11 12 13 14 15 16 17 18 19 20 21 22 23
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup, spawn_text))
.add_systems(
Update,
alter_handle.run_if(input_just_pressed(KeyCode::Space)),
)
.add_systems(
Update,
alter_mesh.run_if(input_just_pressed(KeyCode::Enter)),
)
.run();
}
8 9 10 11 12 13 14 15 16 17 18 19 20 21
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup, spawn_text))
.add_systems(
Update,
alter_handle.run_if(input_just_pressed(KeyCode::Space)),
)
.add_systems(
Update,
alter_asset.run_if(input_just_pressed(KeyCode::Enter)),
)
.run();
}
8 9 10 11 12 13 14 15 16 17 18 19
fn main() {
App::new()
.add_plugins((MinimalPlugins, LogPlugin::default()))
.add_systems(Startup, setup)
.add_systems(
Update,
attack_armor.run_if(on_timer(Duration::from_millis(200))),
)
// Add a global observer that will emit a line whenever an attack hits an entity.
.add_observer(attack_hits)
.run();
}
- examples/ui/overflow_debug.rs
- examples/math/custom_primitives.rs
- examples/games/game_menu.rs
- examples/ecs/generic_system.rs
- examples/3d/post_processing.rs
- examples/2d/sprite_animation.rs
- examples/shader/gpu_readback.rs
- examples/2d/bounding_2d.rs
- examples/games/alien_cake_addict.rs
- examples/asset/multi_asset_sync.rs
- examples/state/custom_transitions.rs
- examples/time/virtual_time.rs
- examples/state/states.rs
- examples/games/stepping.rs
- examples/games/desk_toy.rs
- examples/state/sub_states.rs
- examples/math/render_primitives.rs
- examples/state/computed_states.rs
- examples/ecs/run_conditions.rs
Sourcefn ambiguous_with<M>(
self,
set: impl IntoSystemSet<M>,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn ambiguous_with<M>( self, set: impl IntoSystemSet<M>, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Suppress warnings and errors that would result from these systems having ambiguities
(conflicting access but indeterminate order) with systems in set
.
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();
}
Sourcefn ambiguous_with_all(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn ambiguous_with_all(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Suppress warnings and errors that would result from these systems having ambiguities (conflicting access but indeterminate order) with any other system.
Sourcefn chain(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn chain(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Treat this collection as a sequence of systems.
Ordering constraints will be applied between the successive elements.
If the preceding node on a edge has deferred parameters, a apply_deferred
will be inserted on the edge. If this behavior is not desired consider using
chain_ignore_deferred
instead.
Examples found in repository?
More examples
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(
Update,
(
move_cube,
rotate_cube,
scale_down_sphere_proportional_to_cube_travel_distance,
)
.chain(),
)
.run();
}
- examples/ecs/custom_query_param.rs
- examples/games/contributors.rs
- examples/3d/color_grading.rs
- examples/ecs/one_shot_systems.rs
- examples/3d/motion_blur.rs
- examples/math/cubic_splines.rs
- examples/3d/depth_of_field.rs
- examples/3d/anisotropy.rs
- examples/ecs/send_and_receive_events.rs
- examples/animation/animation_graph.rs
- examples/2d/bounding_2d.rs
- examples/games/breakout.rs
- examples/ecs/fallible_params.rs
- examples/games/stepping.rs
- examples/games/desk_toy.rs
- examples/ecs/event.rs
- examples/ecs/ecs_guide.rs
Sourcefn chain_ignore_deferred(
self,
) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
fn chain_ignore_deferred( self, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>
Treat this collection as a sequence of systems.
Ordering constraints will be applied between the successive elements.
Unlike chain
this will not add apply_deferred
on the edges.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl<P, S> IntoSystemConfigs<(SystemConfigTupleMarker, P)> for (S₁, S₂, …, Sₙ)where
S: IntoSystemConfigs<P>,
impl<P, S> IntoSystemConfigs<(SystemConfigTupleMarker, P)> for (S₁, S₂, …, Sₙ)where
S: IntoSystemConfigs<P>,
This trait is implemented for tuples up to 20 items long.