Commands

Relevant official examples: ecs_guide.


Use Commands to spawn/despawn entities, add/remove components on existing entities, manage resources, from your systems.

fn spawn_things(
    mut commands: Commands,
) {
    // manage resources
    commands.insert_resource(MyResource::new());
    commands.remove_resource::<MyResource>();

    // create a new entity using `spawn`,
    // providing the data for the components it should have
    // (typically using a Bundle)
    commands.spawn(PlayerBundle {
        name: PlayerName("Henry".into()),
        xp: PlayerXp(1000),
        health: Health {
            hp: 100.0, extra: 20.0
        },
        _p: Player,
        sprite: Default::default(),
    });

    // you can use a tuple if you need additional components or bundles
    // (tuples of component and bundle types are considered bundles)
    // (note the extra parentheses)
    let my_entity_id = commands.spawn((
        // add some components
        ComponentA,
        ComponentB::default(),
        // add some bundles
        MyBundle::default(),
        TransformBundle::default(),
    )).id(); // get the Entity (id) by calling `.id()` at the end

    // add/remove components of an existing entity
    commands.entity(my_entity_id)
        .insert(ComponentC::default())
        .remove::<ComponentA>()
        .remove::<(ComponentB, MyBundle)>();

    // remove everything except the given components / bundles
    commands.entity(my_entity_id)
        .retain::<(TransformBundle, ComponentC)>();
}

fn make_all_players_hostile(
    mut commands: Commands,
    // we need the Entity id, to perform commands on specific entities
    query: Query<Entity, With<Player>>,
) {
    for entity in query.iter() {
        commands.entity(entity)
            // add an `Enemy` component to the entity
            .insert(Enemy)
            // remove the `Friendly` component
            .remove::<Friendly>();
    }
}

fn despawn_all_enemies(
    mut commands: Commands,
    query: Query<Entity, With<Enemy>>,
) {
    for entity in query.iter() {
        commands.entity(entity).despawn();
    }
}

When do these actions get applied?

Commands do not take effect immediately, because it wouldn't be safe to modify the data layout in memory when other systems could be running in parallel. When you do anything using Commands, it gets queued to be applied later when it is safe to do so.

Within the same schedule, you can add .before()/.after() ordering constraints to your systems, and Bevy will automatically make sure that Commands get applied in-between if necessary, so that the second system can see the changes made by the first system.

app.add_systems(Update, spawn_new_enemies_if_needed);

// This system will see any newly-spawned enemies when it runs,
// because Bevy will make sure to apply the first system's Commands
// (thanks to the explicit `.after()` dependency)
app.add_systems(Update, enemy_ai.after(spawn_new_enemies_if_needed));

If you do not have explicit ordering dependencies, it is undefined when Commands will be applied. It is possible that some systems will only see the changes on the next frame update!

Otherwise, Commands are normally applied at the end of every schedule. Systems that live in different schedules will see the changes. For example, Bevy's engine systems (that live in PostUpdate) will see the entities you spawn in your systems (that live in Update).

Custom Commands

Commands can also serve as a convenient way to do any custom manipulations that require full access to the ECS World. You can queue up any custom code to run in a deferred fashion, the same way as the standard commands work.

For a one-off thing, you can just pass a closure:

fn my_system(mut commands: Commands) {
    let x = 420;

    commands.add(move |world: &mut World| {
        // do whatever you want with `world` here

        // note: it's a closure, you can use variables from
        // the parent scope/function
        eprintln!("{}", x);
    });
}

If you want something reusable, consider one-shot systems. They are a way to write regular Bevy systems and run them on-demand.

Extending the Commands API

If you want something more integrated, that feels like as if it was part of Bevy's Commands API, here is how to do it.

Create a custom type and implement the Command trait:

use bevy::ecs::world::Command;

struct MyCustomCommand {
    // you can have some parameters
    data: u32,
}

impl Command for MyCustomCommand {
    fn apply(self, world: &mut World) {
        // do whatever you want with `world` and `self.data` here
    }
}

// use it like this
fn my_other_system(mut commands: Commands) {
    commands.add(MyCustomCommand {
        data: 920, // set your value
    });
}

And if you want to make it extra nice to use, you can create an extension trait to add extra methods to Commands:

pub trait MyCustomCommandsExt {
    // define a method that we will be able to call on `commands`
    fn do_custom_thing(&mut self, data: u32);
}

// implement our trait for Bevy's `Commands`
impl<'w, 's> MyCustomCommandsExt for Commands<'w, 's> {
    fn do_custom_thing(&mut self, data: u32) {
        self.add(MyCustomCommand {
            data,
        });
    }
}

fn my_fancy_system(mut commands: Commands) {
    // now we can call our custom method just like Bevy's `spawn`, etc.
    commands.do_custom_thing(42);
}

Note: if you want to use your custom extension method from other Rust files, you will have to import your trait, or it will not be available:

use crate::thing::MyCustomCommandsExt;