Tainted \\ Coders

Run a system conditionally

Last updated:

Use run conditions when adding the system to your app. We can use multiple conditions separately to combine logic for whether the system is skipped or not.

use bevy::prelude::*;

#[derive(Resource)]
struct InputCounter(u32);

fn increment_input_counter(mut input_counter: ResMut<InputCounter>) {
    input_counter.0 += 1;
}

fn has_user_input(input_counter: Res<InputCounter>) -> bool {
    input_counter.0 > 0
}

fn main() {
    App::new()
        .add_systems(
            Update,
            increment_input_counter
                // The common_conditions module has a few useful run conditions
                // for checking resources and states. These are included in the prelude.
                .run_if(resource_exists::<InputCounter>)
                // This is a custom run condition, defined using a system that returns
                // a `bool` and which has read-only `SystemParam`s.
                // Both run conditions must return `true` in order for the system to run.
                // Note that this second run condition will be evaluated even if the first returns `false`.
                .run_if(has_user_input),
        )
        .run();
}

The run conditions will run every time before our system is about to be called and skipped if either condition returns false. Using the same run conditions on different systems will run them separately for each system.

Here we are only checking a single system, but we can also run sets of systems conditionally:

fn main() {
    App::new()
        .add_systems(
            Update,
            (increment_input_counter, some_other_system)
                .run_if(resource_exists::<InputCounter>)
                .run_if(has_user_input),
        )
        .run();
}

This will run the condition before the set of systems, instead of separately before each system runs.

These conditions like resource_exists are defined in 3 separate modules: