What problem does this solve or what need does it fill?
Currently it isn't simple to create and manage SystemIds. For them to be widely used, there needs to be a simple way to work with them.
Reasons they are hard to create:
&mut World is required to create them.
Can't inline register_system in spawn arguments because both take &mut World.
Reasons they are hard to manage:
It is hard to know when to remove the system.
They could be used by many Resources or Components
What solution would you like?
Manage SystemId lifetimes using a new type. I propose SystemHandle. It would act like an asset Handle where it keeps track of references and removes the system when it is no longer being used.
Also an easy way to create SystemHandles. I would suggest a new type that acts like one of AssetServer, Assets, or Commands.
In the future SystemHandle could be used by scenes to reference systems. Maybe the TypeId of the system could be used in a SystemPath. This would require the systems to be registered ahead of time. This can be done in Plugins like so: app.world.register_system(system).
What alternative(s) have you considered?
We could add a methods to Commands and ChildBuilder for creating handles instead of creating a new type to create SystemHandles. This has the drawback that you can't inline creating a SystemHandle in the arguments of spawn.
Is it possible to use the asset system for this and just use Handle<SystemId>? Would this be a good idea even if it were possible?
What problem does this solve or what need does it fill?
Currently it isn't simple to create and manage
SystemId
s. For them to be widely used, there needs to be a simple way to work with them.Reasons they are hard to create:
&mut World
is required to create them.register_system
inspawn
arguments because both take&mut World
.Reasons they are hard to manage:
Resource
s orComponent
sWhat solution would you like?
Manage
SystemId
lifetimes using a new type. I proposeSystemHandle
. It would act like an assetHandle
where it keeps track of references and removes the system when it is no longer being used.Also an easy way to create
SystemHandle
s. I would suggest a new type that acts like one ofAssetServer
,Assets
, orCommands
.In the future
SystemHandle
could be used by scenes to reference systems. Maybe theTypeId
of the system could be used in aSystemPath
. This would require the systems to be registered ahead of time. This can be done inPlugin
s like so:app.world.register_system(system)
.What alternative(s) have you considered?
We could add a methods to
Commands
andChildBuilder
for creating handles instead of creating a new type to createSystemHandles
. This has the drawback that you can't inline creating aSystemHandle
in the arguments ofspawn
.Is it possible to use the asset system for this and just use
Handle<SystemId>
? Would this be a good idea even if it were possible?Additional context
I quickly wrote a proof of concept plugin:
Plugin
```rust use crossbeam_channel::{Receiver, Sender}; use std::sync::{Arc, OnceLock}; use bevy::{ ecs::system::{CommandQueue, SystemId, SystemParam}, prelude::*, }; pub struct OneShotSystemsPlugin; impl Plugin for OneShotSystemsPlugin { fn build(&self, app: &mut App) { let (drop_sender, drop_receiver) = crossbeam_channel::unbounded(); app.insert_resource(SystemHandleProvider { drop_sender, drop_receiver, }) .add_systems(Last, clean_up_system_ids); } } #[derive(SystemParam)] pub struct Systems<'w, 's> { queue: Deferred<'s, CommandQueue>, systems_server: Res<'w, SystemHandleProvider>, } #[derive(Resource)] struct SystemHandleProvider { drop_sender: SenderHere is an example of how I use it to spawn a button:
Example usage
```rust // system for setting up a main menu fn setup_main_menu(mut commands: Commands, mut systems: Systems, asset_server: Res