bevyengine / bevyengine/bevy

Allow cycles in required components

Open
#21,196 6 comments 1 reaction 0 assignees View on GitHub
A-ECS C-Feature C-Usability D-Complex D-Domain-Agnostic
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.