Component Removal Actions for Required Component Enforcement #18514
Labels
A-ECS
Entities, components, systems, and events
C-Feature
A new feature, making something new possible
X-Controversial
There is active debate or serious implications around merging this PR
What problem does this solve or what need does it fill?
Currently, required components are not enforced. If
A
requiresB
, andA
is spawned on an entity, the entity has bothA
andB
, but a user could just removeB
, leavingA
without its requirement. This is intended behavior, but in cases whereA
can not function withoutB
, it may be useful to make the requirement an invariant. As I understand it, this is the case for lots of rendering components, and this invariant has to be manually checked. If we make the ECS enforce this, the extra work to check can be removed, leading to rendering performance improvements. Other performance improvements may be possible. For exampleTransform
would no longer need to make sure it hasGlobalTransform
, etc. In the long run, we may even be able to use this to improveQuery
performance.What solution would you like?
I have done some experimenting and have created a functional prototype of the feature. (See here.)
However, after working on it, I think it would be better to generalize, and open up these "removal actions" to be applicable to more than just requirements.
In this example,
also
states that whenA
is removed,B
is also removed,when
states that whenC
is removed,A
is removed,without
states thatA
is only removed whenD
is not present, andstops
states that whenA
is present,E
can not be removed.Note that
also
andwhen
are inverses, andwithout
andstops
are inverses. We could also include other options, for example,panics_with
, etc.These removal actions can be registered similarly to but separate from required components. In my prototype, I tied these directly to required components, but that is both limiting and problematic. For example, if
A
requiresB
which requiresC
, andA
wants to enforce an invariant with its indirect requirement ofC
without overwriting theB
's constructor forC
, this is impossible without separating required components from removal actions. This separation could result in other uses for removal actions, but the primary use would still be to enforce invariants.When creating
BundleInfo
, we collect these removal actions, and during component removal, we just iterate a newremoved_components
instead ofexplicit_components
.What alternative(s) have you considered?
This could sort of be done via hooks, but that would be slower than adding direct support for it, and it would make reflexive actions more difficult. In the above example,
also
would be easy, butwhen
would require accessingC
's hooks, which could have conflicts, etc.We could make such a thing as a
RemovalGroup
, whereBundle
deals with what is inserted/spawned, butRemovalGroup
deals with what is removed/taken. This could be a nice generalization, but I think this refactor is kinda tangential to this.Roadmap
BundleRemover
this has been a todo item in the ECS for a while, and the refactor will make this feature easier to implement.also
andwhen
.World
for plugins.without
andstops
.panics_with
andcauses_panic_of
if desired.The text was updated successfully, but these errors were encountered: