Skip to content

SystemId scene templating#24087

Open
ItsDoot wants to merge 2 commits intobevyengine:mainfrom
ItsDoot:ecs/systemidtemplate
Open

SystemId scene templating#24087
ItsDoot wants to merge 2 commits intobevyengine:mainfrom
ItsDoot:ecs/systemidtemplate

Conversation

@ItsDoot
Copy link
Copy Markdown
Contributor

@ItsDoot ItsDoot commented May 2, 2026

Objective

I have a bunch of Bundle-style code that I want to replace with the new bsn! Scene-style macro:

pub fn rest_ui(/* system params */) {
    // my ui system...
}

// From
pub fn rest(mut commands: Commands) -> impl Bundle {
    (
        Rest,
        Name::new("Rest"),
        Activity {
            render: commands.register_system(rest_ui),
        },
    )
}

// To (ideally)
pub fn rest() -> impl Scene {
    bsn! {
        Rest
        Name("Rest")
        Activity {
            render: rest_ui
        }
    }
}

Solution

This solution is more inspired by how HandleTemplate works.

  1. Added SystemIdTemplate; it stores either a SystemId or a Arc<Mutex<Either<SystemId, Box<dyn System>>>>
  2. Added a system_value function for wrapping system functions (see Future Work for potentially removing the need)

Testing

  • Added a unit test for SystemIdTemplate.
  • Added to the callbacks example demonstrating how to spawn SystemIds via BSN scenes.

Future work


Showcase

You can now spawn components containing SystemIds via bsn! macros:

#[derive(Component, FromTemplate)]
struct Callback {
    system_id: SystemId<(), ()>,
}

fn my_scene() -> impl Scene {
    bsn! {
        Callback {
            system_id: system_value(|| {
                println!("This is a callback spawned via a scene.");
            })
        }
    }
}

@ItsDoot ItsDoot added A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use A-Scenes Composing and serializing ECS objects D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels May 2, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in ECS May 2, 2026
@laundmo
Copy link
Copy Markdown
Contributor

laundmo commented May 3, 2026

Glad to see my idea from #24072 (comment) had some merit! I won't approve yet, since i've only looked through it on my phone, but it already seems far simpler.

@SkiFire13
Copy link
Copy Markdown
Contributor

This was proposed basically 1:1 in #24026 (this was later changed though). The issue is that it's unclear who owns these systems, that is who is responsible for unregistering them once they are no longer needed. Given that recreating the template will spawn the system again this basically becomes a memory leak.

@laundmo
Copy link
Copy Markdown
Contributor

laundmo commented May 3, 2026

This was proposed basically 1:1 in #24026 (this was later changed though). The issue is that it's unclear who owns these systems, that is who is responsible for unregistering them once they are no longer needed. Given that recreating the template will spawn the system again this basically becomes a memory leak.

Hm, are you sure this is the case even tho in build_template it only registers the system the first time its called, switching over to storing the SystemId after the first call?

@SkiFire13
Copy link
Copy Markdown
Contributor

Hm, are you sure this is the case even tho in build_template it only registers the system the first time its called, switching over to storing the SystemId after the first call?

If you recreate the template (e.g. you call my_scene() again) then you will create a new instance of the system. And since the system is not scoped to the scene once the scene is despawned the system entity will be leaked.

@chescock
Copy link
Copy Markdown
Contributor

chescock commented May 3, 2026

The issue is that it's unclear who owns these systems, that is who is responsible for unregistering them once they are no longer needed. Given that recreating the template will spawn the system again this basically becomes a memory leak.

Would it work to use register_system_cached instead of register_system here?

Then it's not a leak because we could always use the SystemId again, even by recreating the scene. It also avoids some edge cases if you try to use a scene with multiple worlds. And you could probably require the IntoSystem to be Clone and avoid needing Arcs, since ZST systems are usually Clone anyway.

If the systems need to capture values, then maybe those values could be stored as components on the parent entity instead of in the system? The system could take In<Entity> and then have a Query to look up the values. I don't know enough about the actual use cases to know how awkward that transformation would be.

@SkiFire13
Copy link
Copy Markdown
Contributor

Would it work to use register_system_cached instead of register_system here?

You cannot use register_system_cached with a BoxedSystem<I, O>. You need to have a concrete system type that is also a ZST. I don't see an easy way to do that here.

@chescock
Copy link
Copy Markdown
Contributor

chescock commented May 3, 2026

You cannot use register_system_cached with a BoxedSystem<I, O>. You need to have a concrete system type that is also a ZST. I don't see an easy way to do that here.

Right, you'd have to wrap the register call. It would be approximately Box::new(move |world| world.register_system_cached(s)). Except I think Box<dyn Fn> can't be Clone, so you'd need something like Box<dyn Template> with a separate template type.

@ItsDoot
Copy link
Copy Markdown
Contributor Author

ItsDoot commented May 4, 2026

Hm, are you sure this is the case even tho in build_template it only registers the system the first time its called, switching over to storing the SystemId after the first call?

If you recreate the template (e.g. you call my_scene() again) then you will create a new instance of the system. And since the system is not scoped to the scene once the scene is despawned the system entity will be leaked.

I've come up with a bevy_asset::Handle style solution to this problem in #24114, dubbed SystemHandles.

@cart cart closed this May 5, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in ECS May 5, 2026
@cart cart reopened this May 5, 2026
@github-project-automation github-project-automation Bot moved this from Done to Needs SME Triage in ECS May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events A-Scenes Composing and serializing ECS objects C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

5 participants