Trait bevy::ecs::schedule::Condition

pub trait Condition<Marker, In = ()>: Condition<Marker, In> {
    // Provided methods
    fn and<M, C>(
        self,
        and: C,
    ) -> CombinatorSystem<AndMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn and_then<M, C>(
        self,
        and_then: C,
    ) -> CombinatorSystem<AndMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn nand<M, C>(
        self,
        nand: C,
    ) -> CombinatorSystem<NandMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn nor<M, C>(
        self,
        nor: C,
    ) -> CombinatorSystem<NorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn or<M, C>(
        self,
        or: C,
    ) -> CombinatorSystem<OrMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn or_else<M, C>(
        self,
        or_else: C,
    ) -> CombinatorSystem<OrMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn xnor<M, C>(
        self,
        xnor: C,
    ) -> CombinatorSystem<XnorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
    fn xor<M, C>(
        self,
        xor: C,
    ) -> CombinatorSystem<XorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
       where C: Condition<M, In> { ... }
}
Expand description

A system that determines if one or more scheduled systems should run.

Implemented for functions and closures that convert into System<Out=bool> with read-only parameters.

§Marker type parameter

Condition trait has Marker type parameter, which has no special meaning, but exists to work around the limitation of Rust’s trait system.

Type parameter in return type can be set to <()> by calling IntoSystem::into_system, but usually have to be specified when passing a condition to a function.

fn not_condition<Marker>(a: impl Condition<Marker>) -> impl Condition<()> {
   IntoSystem::into_system(a.map(|x| !x))
}

§Examples

A condition that returns true every other time it’s called.

fn every_other_time() -> impl Condition<()> {
    IntoSystem::into_system(|mut flag: Local<bool>| {
        *flag = !*flag;
        *flag
    })
}

schedule.add_systems(my_system.run_if(every_other_time()));

A condition that takes a bool as an input and returns it unchanged.

fn identity() -> impl Condition<(), bool> {
    IntoSystem::into_system(|In(x)| x)
}

app.add_systems(my_system.run_if(always_true.pipe(identity())));

Provided Methods§

fn and<M, C>( self, and: C, ) -> CombinatorSystem<AndMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that only returns true if both this one and the passed and return true.

The returned run condition is short-circuiting, meaning and will only be invoked if self returns true.

§Examples
use bevy_ecs::prelude::*;

#[derive(Resource, PartialEq)]
struct R(u32);

app.add_systems(
    // The `resource_equals` run condition will panic since we don't initialize `R`,
    // just like if we used `Res<R>` in a system.
    my_system.run_if(resource_equals(R(0))),
);

Use .and() to avoid checking the condition.

app.add_systems(
    // `resource_equals` will only get run if the resource `R` exists.
    my_system.run_if(resource_exists::<R>.and(resource_equals(R(0)))),
);

Note that in this case, it’s better to just use the run condition resource_exists_and_equals.

Examples found in repository?
examples/ecs/run_conditions.rs (lines 37-42)
5
6
7
8
9
10
11
12
13
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() {
    println!();
    println!("For the first 2 seconds you will not be able to increment the counter");
    println!("Once that time has passed you can press space, enter, left mouse, right mouse or touch the screen to increment the counter");
    println!();

    App::new()
        .add_plugins(DefaultPlugins)
        .init_resource::<InputCounter>()
        .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>)
                    // `.or()` is a run condition combinator that only evaluates the second condition
                    // if the first condition returns `false`. This behavior is known as "short-circuiting",
                    // and is how the `||` operator works in Rust (as well as most C-family languages).
                    // In this case, the `has_user_input` run condition will be evaluated since the `Unused` resource has not been initialized.
                    .run_if(resource_exists::<Unused>.or(
                        // 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`.
                        has_user_input,
                    )),
                print_input_counter
                    // `.and()` is a run condition combinator that only evaluates the second condition
                    // if the first condition returns `true`, analogous to the `&&` operator.
                    // In this case, the short-circuiting behavior prevents the second run condition from
                    // panicking if the `InputCounter` resource has not been initialized.
                    .run_if(resource_exists::<InputCounter>.and(
                        // This is a custom run condition in the form of a closure.
                        // This is useful for small, simple run conditions you don't need to reuse.
                        // All the normal rules still apply: all parameters must be read only except for local parameters.
                        |counter: Res<InputCounter>| counter.is_changed() && !counter.is_added(),
                    )),
                print_time_message
                    // This function returns a custom run condition, much like the common conditions module.
                    // It will only return true once 2 seconds have passed.
                    .run_if(time_passed(2.0))
                    // You can use the `not` condition from the common_conditions module
                    // to inverse a run condition. In this case it will return true if
                    // less than 2.5 seconds have elapsed since the app started.
                    .run_if(not(time_passed(2.5))),
            ),
        )
        .run();
}

fn and_then<M, C>( self, and_then: C, ) -> CombinatorSystem<AndMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

👎Deprecated: Users should use the .and(condition) method in lieu of .and_then(condition)

Returns a new run condition that only returns true if both this one and the passed and_then return true.

The returned run condition is short-circuiting, meaning and_then will only be invoked if self returns true.

§Examples
use bevy_ecs::prelude::*;

#[derive(Resource, PartialEq)]
struct R(u32);

app.add_systems(
    // The `resource_equals` run condition will panic since we don't initialize `R`,
    // just like if we used `Res<R>` in a system.
    my_system.run_if(resource_equals(R(0))),
);

Use .and_then() to avoid checking the condition.

app.add_systems(
    // `resource_equals` will only get run if the resource `R` exists.
    my_system.run_if(resource_exists::<R>.and_then(resource_equals(R(0)))),
);

Note that in this case, it’s better to just use the run condition resource_exists_and_equals.

fn nand<M, C>( self, nand: C, ) -> CombinatorSystem<NandMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that only returns false if both this one and the passed nand return true.

The returned run condition is short-circuiting, meaning nand will only be invoked if self returns true.

§Examples
use bevy::prelude::*;

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum PlayerState {
    Alive,
    Dead,
}

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum EnemyState {
    Alive,
    Dead,
}

app.add_systems(
    // The game_over_credits system will only execute if either the `in_state(PlayerState::Alive)`
    // run condition or `in_state(EnemyState::Alive)` run condition evaluates to `false`.
    game_over_credits.run_if(
        in_state(PlayerState::Alive).nand(in_state(EnemyState::Alive))
    ),
);

Equivalent logic can be achieved by using not in concert with and:

app.add_systems(
    game_over_credits.run_if(
        not(in_state(PlayerState::Alive).and(in_state(EnemyState::Alive)))
    ),
);

fn nor<M, C>( self, nor: C, ) -> CombinatorSystem<NorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that only returns true if both this one and the passed nor return false.

The returned run condition is short-circuiting, meaning nor will only be invoked if self returns false.

§Examples
use bevy::prelude::*;

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum WeatherState {
    Sunny,
    Cloudy,
}

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum SoilState {
    Fertilized,
    NotFertilized,
}

app.add_systems(
    // The slow_plant_growth system will only execute if both the `in_state(WeatherState::Sunny)`
    // run condition and `in_state(SoilState::Fertilized)` run condition evaluate to `false`.
    slow_plant_growth.run_if(
        in_state(WeatherState::Sunny).nor(in_state(SoilState::Fertilized))
    ),
);

Equivalent logic can be achieved by using not in concert with or:

app.add_systems(
    slow_plant_growth.run_if(
        not(in_state(WeatherState::Sunny).or(in_state(SoilState::Fertilized)))
    ),
);

fn or<M, C>( self, or: C, ) -> CombinatorSystem<OrMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that returns true if either this one or the passed or return true.

The returned run condition is short-circuiting, meaning or will only be invoked if self returns false.

§Examples
use bevy_ecs::prelude::*;

#[derive(Resource, PartialEq)]
struct A(u32);

#[derive(Resource, PartialEq)]
struct B(u32);

app.add_systems(
    // Only run the system if either `A` or `B` exist.
    my_system.run_if(resource_exists::<A>.or(resource_exists::<B>)),
);
Examples found in repository?
examples/math/render_primitives.rs (line 48)
12
13
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
55
fn main() {
    let mut app = App::new();

    app.add_plugins(DefaultPlugins)
        .init_state::<PrimitiveSelected>()
        .init_state::<CameraActive>();

    // cameras
    app.add_systems(Startup, (setup_cameras, setup_lights, setup_ambient_light))
        .add_systems(
            Update,
            (
                update_active_cameras.run_if(state_changed::<CameraActive>),
                switch_cameras.run_if(input_just_pressed(KeyCode::KeyC)),
            ),
        );

    // text

    // PostStartup since we need the cameras to exist
    app.add_systems(PostStartup, setup_text);
    app.add_systems(
        Update,
        (update_text.run_if(state_changed::<PrimitiveSelected>),),
    );

    // primitives
    app.add_systems(Startup, (spawn_primitive_2d, spawn_primitive_3d))
        .add_systems(
            Update,
            (
                switch_to_next_primitive.run_if(input_just_pressed(KeyCode::ArrowUp)),
                switch_to_previous_primitive.run_if(input_just_pressed(KeyCode::ArrowDown)),
                draw_gizmos_2d.run_if(in_mode(CameraActive::Dim2)),
                draw_gizmos_3d.run_if(in_mode(CameraActive::Dim3)),
                update_primitive_meshes
                    .run_if(state_changed::<PrimitiveSelected>.or(state_changed::<CameraActive>)),
                rotate_primitive_2d_meshes,
                rotate_primitive_3d_meshes,
            ),
        );

    app.run();
}
More examples
Hide additional examples
examples/ecs/run_conditions.rs (lines 25-31)
5
6
7
8
9
10
11
12
13
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() {
    println!();
    println!("For the first 2 seconds you will not be able to increment the counter");
    println!("Once that time has passed you can press space, enter, left mouse, right mouse or touch the screen to increment the counter");
    println!();

    App::new()
        .add_plugins(DefaultPlugins)
        .init_resource::<InputCounter>()
        .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>)
                    // `.or()` is a run condition combinator that only evaluates the second condition
                    // if the first condition returns `false`. This behavior is known as "short-circuiting",
                    // and is how the `||` operator works in Rust (as well as most C-family languages).
                    // In this case, the `has_user_input` run condition will be evaluated since the `Unused` resource has not been initialized.
                    .run_if(resource_exists::<Unused>.or(
                        // 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`.
                        has_user_input,
                    )),
                print_input_counter
                    // `.and()` is a run condition combinator that only evaluates the second condition
                    // if the first condition returns `true`, analogous to the `&&` operator.
                    // In this case, the short-circuiting behavior prevents the second run condition from
                    // panicking if the `InputCounter` resource has not been initialized.
                    .run_if(resource_exists::<InputCounter>.and(
                        // This is a custom run condition in the form of a closure.
                        // This is useful for small, simple run conditions you don't need to reuse.
                        // All the normal rules still apply: all parameters must be read only except for local parameters.
                        |counter: Res<InputCounter>| counter.is_changed() && !counter.is_added(),
                    )),
                print_time_message
                    // This function returns a custom run condition, much like the common conditions module.
                    // It will only return true once 2 seconds have passed.
                    .run_if(time_passed(2.0))
                    // You can use the `not` condition from the common_conditions module
                    // to inverse a run condition. In this case it will return true if
                    // less than 2.5 seconds have elapsed since the app started.
                    .run_if(not(time_passed(2.5))),
            ),
        )
        .run();
}

fn or_else<M, C>( self, or_else: C, ) -> CombinatorSystem<OrMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

👎Deprecated: Users should use the .or(condition) method in lieu of .or_else(condition)

Returns a new run condition that returns true if either this one or the passed or return true.

The returned run condition is short-circuiting, meaning or will only be invoked if self returns false.

§Examples
use bevy_ecs::prelude::*;

#[derive(Resource, PartialEq)]
struct A(u32);

#[derive(Resource, PartialEq)]
struct B(u32);

app.add_systems(
    // Only run the system if either `A` or `B` exist.
    my_system.run_if(resource_exists::<A>.or(resource_exists::<B>)),
);

fn xnor<M, C>( self, xnor: C, ) -> CombinatorSystem<XnorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that only returns true if self and xnor both return false or both return true.

§Examples
use bevy::prelude::*;

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum CoffeeMachineState {
    Heating,
    Brewing,
    Inactive,
}

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum TeaKettleState {
    Heating,
    Steeping,
    Inactive,
}

app.add_systems(
    // The take_drink_orders system will only execute if the `in_state(CoffeeMachineState::Inactive)`
    // run condition and `in_state(TeaKettleState::Inactive)` run conditions both evaluate to `false`,
    // or both evaluate to `true`.
    take_drink_orders.run_if(
        in_state(CoffeeMachineState::Inactive).xnor(in_state(TeaKettleState::Inactive))
    ),
);

Equivalent logic can be achieved by using not in concert with xor:

app.add_systems(
    take_drink_orders.run_if(
        not(in_state(CoffeeMachineState::Inactive).xor(in_state(TeaKettleState::Inactive)))
    ),
);

fn xor<M, C>( self, xor: C, ) -> CombinatorSystem<XorMarker, Self::System, <C as IntoSystem<In, bool, M>>::System>
where C: Condition<M, In>,

Returns a new run condition that only returns true if either self or xor return true, but not both.

§Examples
use bevy::prelude::*;

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum CoffeeMachineState {
    Heating,
    Brewing,
    Inactive,
}

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
pub enum TeaKettleState {
    Heating,
    Steeping,
    Inactive,
}

app.add_systems(
    // The prepare_beverage system will only execute if either the `in_state(CoffeeMachineState::Inactive)`
    // run condition or `in_state(TeaKettleState::Inactive)` run condition evaluates to `true`,
    // but not both.
    prepare_beverage.run_if(
        in_state(CoffeeMachineState::Inactive).xor(in_state(TeaKettleState::Inactive))
    ),
);

Object Safety§

This trait is not object safe.

Implementors§

§

impl<Marker, In, F> Condition<Marker, In> for F
where F: Condition<Marker, In>,