Skip to content

Commands that run for a given entity #6156

Closed
@joseph-gio

Description

@joseph-gio

What problem does this solve or what need does it fill?

In my crate bevy_mouse_tracking, users need to be able to insert components in a fully-initialized state. This initialization requires access to the world, which means the most natural way to express this is through commands. Currently, this would look like

// Library-side
pub struct InsertInitialized(pub Entity);
impl Command for InsertInitialized {
    fn write(self, world: &mut World) {
        let initialized = perform_initialization(self.0, world);
        world.entity(self.0).insert(initialized);
    }
}

// User-side
fn my_system(mut commands: Commands) {
    let my_entity = commands.spawn_empty().id();
    commands.add(InsertInitialized(my_entity));
}

This is very cumbersome on the user side.

What solution would you like?

Add a trait for commands that run for a given entity.

pub trait EntityCommand: Send + 'static {
    fn write_for(self, _: Entity, _: &mut World);
    fn with_entity(self, _: Entity) -> impl Command { ... }
}

The previous example now becomes:

// Library-side
pub struct InsertInitialized;
impl EntityCommand for InsertInitialized {
    fn write_for(self, entity: Entity, world: &mut World) {
        let initialized = perform_initialization(entity, world);
        world.entity(entity).insert(initialized);
    }
}

// User-side
fn my_system(mut commands: Commands) {
    commands.spawn_empty().add_command(InsertInitialized);
}

What alternative(s) have you considered?

My current workaround is to add extension methods to EntityCommands (the struct, not this proposed trait) for each custom command. This is only slightly less annoying for users, as it requires them to bring an extension trait into scope. I don't think this is practical in the general case.

Additional context

This could also be used to implement built-in commands, such as GetOrSpawn, Insert, Despawn, etc. This would make direct use of these types more ergonomic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-UsabilityA targeted quality-of-life change that makes Bevy easier to use

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions