Skip to content

SystemRunner param - run systems inside other systems #16680

Open
@vil-mo

Description

@vil-mo

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

Currently ways of running systems from other systems are very limited. This proposal aims to provide a way to easily run system as a SystemParam

What solution would you like?

Add a SystemParam - SystemRunner<T: System + FromWorld>

#[derive(Default)]
struct MySystem;
impl System for MySystem {
    In = In<i32>;
    Out = String;
    //...
}

fn running_my_system(mut runner: SystemRunner<MySystem>) {
    let output = runner.run(50);
    info!("Output of MySystem: {output}");
}

Unergonomic System implementation

To use this param, user would have to explicitly specify the type of the system they will use. Implementing System trait on it's own is hard - unsafe code is not something users want to deal with. FunctionSystems are the main way people are used to working with the bevy systems, but they don't implement FromWorld, and even if it did, you would have to either specify the marker or box every system.

So, it would be nice to have a macro that labels a function system with a specified type name.

#[system(MySystem)]
pub fn my_system(query: Query<&mut MyComponent>, resourse: Res<MyRes>) -> i32 {
    //...
}

expands to

pub struct MySystem(SystemState<(Query<'static, 'static, &'static mut MyComponent>, Res<'static, MyRes>)>);

impl FromWorld for MySystem {
    fn from_world(world: &mut World) -> Self {
        MySystem(SystemState::new(world))
    }
}

impl System for MySystem {
    //... Basically the same as FunctionSystem implementation
}

Needed controversial change

There is a conflict between System::update_archetype_component_access and SystemParam::new_archetype. You can't call update_archetype_component_access from new_archetype. Without that you wouldn't be able to call update_archetype_component_access on an inner system and simultaneously have access rights to run the system.

We can add a new_archetype method to System trait or update_archetype_component_access to SystemParam trait. We can pass UnsafeWorldCell to the new_archetype.

The best option in my opinion - add a new_archetype method to the System trait. There will be system-specific code for updating access. update_archetype_component_access will have a default implementation common for all systems. It will be basically the same as the current FunctionSystem's implementation. Systems would also need a method that exposes system's archetype generation for update_archetype_component_access to have default implementation. Method that exposes archetype generation should be fallible so that ZST systems can say that they don't need to update archetype access.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-FeatureA new feature, making something new possibleD-ModestA "normal" level of difficulty; suitable for simple features or challenging fixesS-Nominated-To-CloseA triage team member thinks this PR or issue should be closed out.X-ControversialThere is active debate or serious implications around merging this PR

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions