bevy::ecs::prelude

Trait IntoSystemConfigs

Source
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§

Source

fn into_configs(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>

Convert into a SystemConfigs.

Provided Methods§

Source

fn in_set( self, set: impl SystemSet, ) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>

Add these systems to the provided set.

Examples found in repository?
examples/stress_tests/many_lights.rs (line 161)
156
157
158
159
160
161
162
    fn build(&self, app: &mut App) {
        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
            return;
        };

        render_app.add_systems(Render, print_visible_light_count.in_set(RenderSet::Prepare));
    }
More examples
Hide additional examples
examples/shader/custom_shader_instancing.rs (line 103)
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),
                ),
            );
    }
examples/shader/gpu_readback.rs (line 51)
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());
    }
examples/shader/compute_shader_game_of_life.rs (line 108)
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);
    }
examples/2d/mesh2d_manual.rs (line 314)
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));
    }
examples/shader/custom_phase_item.rs (line 178)
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();
}
Source

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.

Source

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 Systems 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?
examples/3d/skybox.rs (line 46)
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
Hide additional examples
examples/ecs/one_shot_systems.rs (line 24)
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();
}
examples/ui/ui_scaling.rs (line 18)
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();
}
examples/3d/reflection_probes.rs (line 74)
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();
}
examples/3d/post_processing.rs (line 42)
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();
}
examples/app/headless_renderer.rs (line 215)
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));
    }
Source

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.

Source

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.

Source

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.

Source

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?
examples/diagnostics/enabling_disabling_diagnostic.rs (line 20)
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
Hide additional examples
examples/remote/server.rs (line 17)
11
12
13
14
15
16
17
18
19
20
21
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(RemotePlugin::default())
        .add_plugins(RemoteHttpPlugin::default())
        .add_systems(Startup, setup)
        .add_systems(Update, remove.run_if(input_just_pressed(KeyCode::Space)))
        .add_systems(Update, move_cube)
        .register_type::<Cube>()
        .run();
}
examples/asset/alter_mesh.rs (line 16)
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();
}
examples/asset/alter_sprite.rs (line 14)
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();
}
examples/2d/texture_atlas.rs (line 17)
12
13
14
15
16
17
18
19
20
fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) // fallback to nearest sampling
        .init_state::<AppState>()
        .add_systems(OnEnter(AppState::Setup), load_textures)
        .add_systems(Update, check_textures.run_if(in_state(AppState::Setup)))
        .add_systems(OnEnter(AppState::Finished), setup)
        .run();
}
examples/ecs/observer_propagation.rs (line 14)
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();
}
Source

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?
examples/ecs/nondeterministic_system_order.rs (line 53)
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();
}
Source

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.

Source

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?
examples/gizmos/axes.rs (line 14)
10
11
12
13
14
15
16
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (move_cubes, draw_axes).chain())
        .run();
}
More examples
Hide additional examples
examples/movement/smooth_follow.rs (line 14)
10
11
12
13
14
15
16
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (move_target, move_follower).chain())
        .run();
}
examples/camera/2d_top_down_camera.rs (line 27)
23
24
25
26
27
28
29
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, (setup_scene, setup_instructions, setup_camera))
        .add_systems(Update, (move_player, update_camera).chain())
        .run();
}
examples/transforms/align.rs (line 17)
12
13
14
15
16
17
18
19
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (draw_ship_axes, draw_random_axes))
        .add_systems(Update, (handle_keypress, handle_mouse, rotate_ship).chain())
        .run();
}
examples/3d/clearcoat.rs (line 56)
49
50
51
52
53
54
55
56
57
58
pub fn main() {
    App::new()
        .init_resource::<LightMode>()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, animate_light)
        .add_systems(Update, animate_spheres)
        .add_systems(Update, (handle_input, update_help_text).chain())
        .run();
}
examples/transforms/transform.rs (line 35)
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();
}
Source

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>,

This trait is implemented for tuples up to 20 items long.

Source§

fn into_configs(self) -> NodeConfigs<Box<dyn System<Out = (), In = ()>>>

Implementors§

Source§

impl IntoSystemConfigs<()> for NodeConfigs<Box<dyn System<Out = (), In = ()>>>

Source§

impl IntoSystemConfigs<()> for Box<dyn System<Out = (), In = ()>>

Source§

impl<Marker, F> IntoSystemConfigs<Marker> for F
where F: IntoSystem<(), (), Marker>,