-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add way to hook into entity despawns #2031
Comments
Have you considered accepting that the cache will only be cleared on the next frame, and thus at the beginning of your system querying components that were removed to clear the cache when necessary? |
How do you figure?
If I have `Query<(Entity, &Coordinates)>, cache: Local<HashMap<Entity,
(i32, i32)>>`, then add my entity to that cache, why would it only
persist for the frame? Besides, the whole point of these caches is to
persist entities across frames, and not react on fractional coordinate
changes where it doesn't make sense.
|
Oh, never mind, I see what you mean now. Apologies.
I guess I could clean the cache manually, sure. Thanks, that's a good
workaround for now. Though I still think Bevy should generate some sort
of lifecycle event on despawn.
|
I am glad this can be a good workaround. Could you elaborate on how iterating over those despawn events would differ from iterating over removed components? |
My understanding is that iterating over removed components can only be
done in post-update now. So if you have a system with a `Local`
containing a map of entities to some cached calculated data, you'd have
to run that system once in post-update to catch the removals. That seems
like the kind of footgun that's easy to miss, particularly in cache
cleanup situations where the only indication you'd have looks a lot like
a leak.
|
My apologies, I was not aware of the post-update restriction. My suggested solution thus does not apply. |
Ah, then I guess I misunderstood your suggestion the second time when I
thought I understood it. :)
What I thought you were suggesting was that I iterate through all cached
members and check them against one of my queries via `get`, removing
them manually if I get an `Err`. I think that's an OK temporary
workaround, but I still want to advocate for the far more expressive
`EventReader<EntityLifecycle>` which, IMO, makes it far clearer that I'm
asking the ECS for entity updates and performing some logic based on those.
|
This is true, not because there is something special about PostUpdate, but because Commands are applied at the end of Update. If we were to add a new "entity despawn" event, it would still only be available in PostUpdate because Some folks are working to make Command application more granular within a stage (we're calling it "stageless" right now), which might solve this problem. But in the short term, the only way to make "despawns" immediate is to use "exclusive systems" (systems that take a direct
I do think that this is good thing to add, even though it would have the same limitations the "component removal tracking" has in relationship to Commands. A full entity despawn is semantically different than specific component removals and I imagine there are plenty of legitimate use cases for it. The design for this should probably go through the RFC process as there are a number of ways to implement it (and a number of ways to expose it to the user). |
There is a big limitation of So yay for |
To be clear, I don't care if the removal is delayed a frame and inherits
event limitations. I'm just looking for a way to clean up `Local` caches
in a way that doesn't obfuscate my intent, or require me to run a system
multiple times just to catch `Removed`.
|
Yeah Events are probably the right call. Something to consider for the design: a global EntityLifecycleEvent for all entities might end up being expensive to consume in some cases because you need to iterate over all entity events across all contexts. Sometimes considering them globally will be necessary, but it would be interesting to consider ways to "filter down" events, maybe by storing them per-archetype? Could they be queryable? |
I think this can be closed via #10756, right? |
This probably can be considered closed with component hooks as a MVP. I'd like to see easier access to the inserted or removed components to make this a bit cleaner to use though. |
What problem does this solve or what need does it fill?
Sometimes, to speed up a system, I cache data in something like a
Local<HashMap<Entity, _>>
, and avoid heavier calculations if the cache hasn't changed. Much of this state wouldn't make sense as a separate component, and it feels cleaner to do it as aLocal
. Unfortunately, there's no apparent way to detect if an entity despawns and clean up these local caches.What solution would you like?
Maybe some sort of entity despawn event. Maybe, for symmetry, it could be like:
What alternative(s) have you considered?
I could check whether components used to calculate the cache were removed, but then I'd need to either rerun the system in post-update, or only have a single copy there. That isn't always possible.
I could also externalize the cache, but that feels dirty as it pollutes the module namespace with a) state only relevant to one system and b) a secondary system to clean that state up.
Finally, I could create my own events, but this requires me to manually throw those events whenever I despawn. Given that a) this seems like a general problem and b) Bevy itself knows when it is despawning something, it probably makes more sense for the engine to notify that the entity was despawned.
The text was updated successfully, but these errors were encountered: