Making Required Components force existence as a follow-up of #18514
- 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?
The #18514 proposes a way to enforce the invariant of existence of required components.
While the following opinion can be controversial, I believe that this invariant should be held by default - as even the wording of **Required Components** means that the specified component is *required* for correct behaviour of the component it is specified for.
As for justification of having the API to enforce such a variant - see #18514, it is described there wonderfully that this both improves DX and can improve performance by removing unnecessary checks.
I propose that the behaviour of
```rust
#[removal(stops(B)]
struct A;
```
(states that when `A` is present, `B` can not be removed) should be *the* default behaviour of required components, and that
```rust
#[removal(when(B)]
struct A;
```
(states that when `B` is removed, `A` is also removed) and the current behaviour of allowing to remove the required component afterwards should be options on the required component.
## What solution would you like?
- `#[require(B)]` and `world.register_required_components` now also apply the logic of `#[removal(stops(B)]` by default.
- Add a parameter to `world.register_required_components` for specifying the behaviour of removal tracking.
- If you want the current behaviour of allowing removals of required component on `#[require(B)]`, you should write
```rust
#[require(B, allow_removal)]
struct A;
```
- If you want the behaviour of `#[removal(when(B)]` on `#[require(B)]`, you should write
```rust
#[require(B, removed_alongside)]
struct A;
```
## What alternative(s) have you considered?
Do not change the behaviour, so in most cases the developer would write either (most of the time)
```rust
#[required(B)]
#[removal(stops(B)]
struct A;
```
or like now (second place of commonness) to allow removal
```rust
#[required(B)]
struct A;
```
or (in I think very rare cases)
```rust
#[required(B)]
#[removal(when(B)]
struct A;
```
I personally think this is a worse DX than changing the behaviour of required components.
## Additional context
Unity has the notion of required components in its EC architecture, and it prevents the removal of the required component both in Editor and in Playmode both from Editor UI and from scripts with the error `Can't remove *B* because *A* depends on it`.
Contributor guide
Assessment
This issue has not been assessed yet.