bevyengine / bevyengine/bevy

Support singleton systems

Open
#21,761 3 comments 0 reactions 0 assignees View on GitHub
A-ECS C-Feature S-Needs-Design
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.