Skip to content

Remove SystemId and one-shot systems #24031

@Freyja-moth

Description

@Freyja-moth

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

SystemId was introduced by #8963 to allow users to run one off systems outside of the usual schedules. However since the introduction of observers the need for them has become increasingly obsolete to my mind.

The only advantage of registered systems over observers is that registered systems can: directly return a value (but only when using World), take owned data as input, and you can filter which ones you're using via queries.

Being able to return a value, while nice, doesn't feel any more useful for long term storage than simply making a change to the ecs that you were probably going to make down the line anyways.

Using owned inputs only really makes a difference if you're using constants, or if you're only using one system and the data can't be cloned.

pub struct Container(SystemId<Box<dyn Display>>);

pub struct SpecialInput(Box<dyn Display>);

fn run_containers(
    In(input): In<SpecialInput>,
    mut commands: Commands,
    containers: Query<&Container>,
) {
    for Container(system) in containers {
        // This won't work
        commands.run_system_with(system, input.0);
    }
    
    for Container(system) in containers {
        // This will
        commands.run_system_with(system, Box::new("Hello there"));
    }

    if let Ok(Container(system)) in containers.single() {
        // As will this
        commands.run_system_with(system, input.0);
    }
}

However I'm not convinced that these benefits justify the api space over simply using observers

What solution would you like?

I am in favour of removing SystemId and all of it's associated methods entirely, however I know @chescock has their own thoughts on keeping run_system_cached so I'll let them state their case.

Along with this I would suggest some method that allows observers to be selectively run.

pub struct Special;

pub struct PlayerEntity(Entity);

fn trigger(mut commands: Commands, special_observers: Query<Entity, (With<Observer>, With<Special)>, player: Res<PlayerEntity>) {
    let observers = special_observers
        .iter()
        .collect();

    commands.trigger_entities(Flee { entity: *player }, observers);
}

But this may want to be hidden in some way to prevent new users from getting confused

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-UsabilityA targeted quality-of-life change that makes Bevy easier to useD-ComplexQuite challenging from either a design or technical perspective. Ask for help!S-Needs-DesignThis issue requires design work to think about how it would best be accomplishedX-Needs-SMEThis type of work requires an SME to approve it.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions