Skip to content

Prevent Reading Dead Entities From Component Storage #82

@zicklag

Description

@zicklag

Say you do this.

world.run_system(
  |mut entities: ResMut<Entities>, positions: CompMut<Pos>| 
    // Create an entity
    let entity = entities.create();
    positions.insert(entity, default());

    // Kill that entity
    entities.kill(entity);
    
    // This works
    let pos = positions.get(entity).unwrap();
  });

The issue is that the component storage doesn't know which entities are alive. So if you want this to behave as you would probably expect, you must do something like this:

world.run_system(
  |mut entities: ResMut<Entities>, positions: CompMut<Pos>| 
    // Create an entity
    let entity = entities.create();
    positions.insert(entity, default());

    // Kill that entity
    entities.kill(entity);
    
    // Pre-check entity live-ness
    if entities.is_alive(entity) {
      let pos = positions.get(entity).unwrap();
    }
  });

And that's not cool.


Maybe we can store store the list of valid generations for entities in the component stores, and update that every frame. So the example above would still work counter-intuitively, but after one frame the component store would become aware of the entity being deleted?

That's still kind of confusing.

I'm not sure if we can make some sort of atomic bitset that can efficiently update the list of alive entities across all components. We could put an Arc<AtomicRefCell<Bitset>> or something like that to keep track of alive entities, and then all component storages have a reference to the alive entities, maybe. That might hurt performance because of the locking, but it would only have to lock inefficiently when you have mutable access to the Entities in a system, so maybe that wouldn't be a problem.

I think that any solution that improves the ergonomics here, and doesn't seriously impact performance should probably be considered, even if it isn't perfect, or the fastest thing on the planet.

I haven't done a lot of in-depth thinking about different ways to design the ECS that might remedy this issue. Most of the overall design idea was borrowed from Planck, but there might be some divergence we can make here that might be more efficient and fix the confusion, I'm not sure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions