-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Description
What problem does this solve or what need does it fill?
My physics engine Avian has a lot of state management logic that uses observers or hooks. This logic must be robust, or the simulation can crash or otherwise fail due to invariants not being upheld.
Several instances of this need to know whether Add or Insert was triggered because the entity was spawned, or because the component was explicitly inserted via insert after spawn. Or similarly, whether Replace or Remove was triggered because the entity was despawned, or because the component was explicitly removed via remove.
As an example: When Disabled is removed from a collider entity, I need to insert the collider back into a BVH for it to participate in collision detection. However, if the removal actually happened because the entity was despawned, I don't want to do this, or I'd be inserting a non-existent entity into the BVH. I cannot check if the entity really exists in the Remove observer, because at that point, queries still have access to the entity. I could first insert the entity and then remove it in a Despawn observer, but this is just unnecessary work that can get costly for bulk removal.
What solution would you like?
InsertionReasonenum forAddandInsert, withSpawnedandInsertedvariantsRemovalReasonenum forReplaceandRemove, withDespawnedandInsertedvariants
Naming can be bikeshed, and we could also make these bools or bitflags if we wanted to, though I think an enum makes the most sense.
We should probably add these for the on_add, on_insert, on_replace, and on_remove hooks as well. However these don't currently have their own types where we could store the property without breaking changes, so it might be more controversial. I have less personal need for this right now, so I would be content with only providing the reason enums for observers.
What alternative(s) have you considered?
You can sometimes work around the problem by (ab)using the fact that e.g. Replace runs before Remove, and split logic into several different observers, but it's ugly and often increases overhead. I haven't figured out a good general alternative.
I don't know if/how flecs solves this, but it could be useful to look at them for guidance too.