Run Conditions

Run Conditions (RC) are a mechanism for controlling if Bevy should run specific systems, at runtime. This allows you to enable/disable systems on-demand, so that they only run sometimes.

RCs are Rust functions that return a value of type bool. They can accept any system parameters, like a normal system, but they must all be read-only (immutable).

fn run_if_player_alive(
    q_player: Query<&Health, With<Player>>,
) -> bool {
    let health = q_player.single();
    health.hp > 0.0
}

fn run_if_connected(
    mode: Res<MyMultiplayerMode>,
    session: Res<MyNetworkSession>,
) -> bool
{
    *mode != MyMultiplayerMode::Local && session.is_connected()
}

fn run_if_enemies_present(
    q_enemies: Query<(), With<Enemy>>,
) -> bool {
    !q_enemies.is_empty()
}

RCs can be applied to individual systems or to entire system sets.

app.configure_sets(Update,
    MyPlayerSet
        .run_if(run_if_player_alive)
);

app.add_systems(Update, (
    player_input,
    player_movement,
    player_alert_enemies
        .run_if(run_if_enemies_present)
).in_set(MyPlayerSet));

app.add_systems(Update,
    manage_multiplayer_server
        .run_if(run_if_connected)
);

When applied to a single system, Bevy will evaluate the RC at the last moment, right before the system would otherwise be ready to run. If you add the same RC to multiple systems, Bevy will evaluate it separately for each one.

When applied to a set, the run condition will only be evaluated once, before Bevy runs any system from the set, and if it returns false, the entire set will be skipped.

Any given system can be governed by any number of RCs. You can add multiple RCs to one system, and it will also inherit the RCs of any sets it belongs to. Bevy will evaluate all the RCs, and the system will only run if all of them return true.

Common Conditions

Bevy provides some built-in RCs for some common scenarios, that you can just apply to your systems:

Known Pitfalls

When receiving events in systems that don't run every frame update, you can miss some events that are sent while the receiving systems are not running!

To mitigate this, you could implement a custom cleanup strategy, to manually manage the lifetime of the relevant event types.