Allow cycles in required components
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
This PR: https://github.com/bevyengine/bevy/pull/20110 removed the ability to have cycles in required components (A requires B and B requires A).
This was a very useful feature that helps guarantee archetype invariants: for example if we always want A or B to be present on the entity together, we need A to require B and B to require A.
## What solution would you like?
We use A -> [B(1), C(2)] as a notation for A requires B with constructor 1 and C with constructor 2.
The existing required components [rules](https://github.com/bevyengine/bevy/blob/v0.17.0-rc.2/crates/bevy_ecs/src/component/mod.rs#L284) are:
- components in the bundle take priority over required components (i.e. if we insert (A, B(2)) and A -> [B(1)], only (A, B(2)) is inserted). **Priority 1: inserted components**
- if a component is directly required , that takes priority. **Priority 2: direct components**
- otherwise find it by DFS, starting from the first component in the list of required components. (and we do one DFS per component in the bundle, starting from the component in the bundle) **Priority 3: DFS components**
Additional rule:
- if we during the DFS we reach a component that was already in our DFS stack (cycle in required components), then instead of returning an error we stop the DFS at that point and backtrack
If we use A -> [B] as a notation for A requires B:
- A -> [A] is allowed but does nothing
- A -> [B] and B -> [A] to be allowed
- A -> [B, C(1)] and B -> [C(2), A, D(2)] and C -> [D(1)]:
- if we insert A:
- B and C(1) should be inserted since they are in the list of direct requires
- D(1) should be inserted since we do a DFS starting from B
- if we insert B:
- C(2), A, D(2) should be inserted since they are in the list of direct requires
- A -> [B(1)], B -> [C(1), D(2)], C -> [D(1), B(2)], D -> [A(1), C(2)]
- if we insert A: A, B(1), C(1), D(1) (via DFS)
- if we insert B: B, C(1), D(1), A(1)
- if we insert (C(3), B(3)): C(3), B(3), D(1), A(1) (via DFS)
Contributor guide
Assessment
This issue has not been assessed yet.