Closed LPGhatguy closed 4 months ago
This is an instance of a very general problem, and I'm not sure it makes sense for hecs to try to come up with magic to solve it. Is there a way you could wrap hecs::Entity
for these uses without also wrapping many APIs? Maybe something like:
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct UniversalEntity {
world_id: u64,
entity: hecs::Entity,
}
impl UniversalEntity {
pub fn to_entity(&self, world_id: u64) -> Option<hecs::Entity> {
(self.world_id == world_id).then_some(*self);
}
}
Ensuring that Entity
values stored outside of the World
use UniversalEntity
should be easy compared to never having such bugs to begin with, while not adding large amounts of maintenance load or complicating hecs itself.
As a little help, the existing World::id
field could be made available since hecs already manages it?
Currently,
Entity
values are not tied to any specificWorld
. This has benefits like supporting straightforward serialization.It could be useful if
Entity
were given a world ID field, expanding it fromto
This world ID would ensure that
Entity
values from oneWorld
would never be valid when used with anotherWorld
.Rationale
Recently, we uncovered a data loss bug in our game editor related to our hecs
World
being recreated. It went something like this:Entity
values to reference them.World
. The editor is still holding onto theEntity
values from the previous scene.After finding this issue, I found that a number of our game systems occasionally store
Entity
values from a previousWorld
, and then get confused when those handles now point to completely different objects.We can patch issues like that individually, usually by flushing any stored state whenever we're also changing worlds. However, I think it'd be nice to have a holistic solution to the problem. I came to the conclusion that we had two decent options besides not storing
Entity
values:hecs::World
so that duplicateEntity
values are never created.hecs::Entity
a World ID so that handles created from other worlds are invalid.Option 1 is feasible, but complicates our serialization/deserialization code a bit. Additionally, while we don't currently ever have more than one
World
at a time, I think it would be a shame to fuse off that functionality.I tried to prototype option 2 by wrapping
hecs::Entity
and all related APIs externally, but that turned into quite a mess.I thought it would be a good idea to open this issue to get another read on this problem. Adding more data to
Entity
is likely overkill for a lot of use cases, but does eliminate issues like this very cleanly.Pros
Entity
handles from other worlds or that are stale will never access a new entityHashMap<Entity, T>
for keeping extra state without mixing state between worldsCons
Entity
becomes 12 bytesWorld
needs some way of getting a unique IDEntity
now includes extra dataAlternatives
Entity
themselves and insert extra checksWorld
onlyEntity
references at all, instead using marker components and queriesWorld
objects share anEntity
generation allocator