Support singleton systems
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## What problem does this solve or what need does it fill?
I’m trying to abstract the `MaterialsPlugin` into a more general-purpose plugin, `PassPlugin`. I’ve converted most systems into generic functions, but some systems should only be added once, such as `prepare_material_bind_groups` and `write_material_bind_group_buffers`.
There are workarounds, but they hurt code readability.
I found two similar cases in Bevy’s codebase:
* In `MaterialPlugin`, the [`late_sweep_material_instances`](https://github.com/bevyengine/bevy/blob/7d84e5bed12f035c967facfe689a5b1f294b570d/crates/bevy_pbr/src/material.rs#L764) system should ideally be handled by that plugin, but it was moved into [`PbrPlugin`](https://github.com/bevyengine/bevy/blob/7d84e5bed12f035c967facfe689a5b1f294b570d/crates/bevy_pbr/src/lib.rs#L330) to maintain singleton behavior.
* In `PrepassPlugin`, a resource [`AnyPrepassPluginLoaded`](https://github.com/bevyengine/bevy/blob/7d84e5bed12f035c967facfe689a5b1f294b570d/crates/bevy_pbr/src/prepass/mod.rs#L122) is used as a marker to ensure the system is only added once.
## What solution would you like?
I’d like to be able to add systems as singletons, scoped to a single `World`, similar to how resources work.
The API might look like this:
```rust
app.add_systems(Update, foo_system.singleton());
```
## What alternative(s) have you considered?
Perhaps singleton systems could be the default, and we could explicitly opt into multiple instances with something like `foo_system.duplicate()`.
I'm wondering if there are valid use cases for adding the same system multiple times. One scenario that comes to my mind is adding it to different schedules, where data flow differences would lead to different effects.
Contributor guide
Research direction
Start by reading the singleton workarounds in crates/bevy_pbr/src/material.rs, crates/bevy_pbr/src/lib.rs, and crates/bevy_pbr/src/prepass/mod.rs, especially late_sweep_material_instances and AnyPrepassPluginLoaded. Establish the desired per-World behavior and API for singleton systems, including whether duplicate registration remains possible; done means the design is settled and the affected plugin cases can use it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100