Search Unity

how to deal with "orphan" entities?

Discussion in 'Entity Component System' started by SubPixelPerfect, Oct 21, 2019.

  1. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    2019-10-21_203831.png
    here is a chunk with entities that have no components
    how to query those poor fellows?
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    While you got valid question, I would ask first, how they happened?
     
  3. sschoener

    sschoener

    Joined:
    Aug 18, 2014
    Posts:
    73
    You could create an EntityQuery that explicitly excludes all component types, but that's brittle and would break if you forgot any component or someone else adds one. Alternatively, you could query the chunks themselves. This should do the trick, but I haven't had the time to test it:
    Code (CSharp):
    1. using(var chunks = EntityManager.GetAllChunks()) {
    2.     var bareEntity = EntityManager.GetEntityOnlyArchetype();
    3.     UnityEngine.Debug.Assert(bareEntity.GetComponentTypes().Length == 0);
    4.     for (int c = 0; c < chunks.Length; c++) {
    5.         if (chunks[c].Archetype == bareEntity) {
    6.             // do your thing here.
    7.         }
    8.     }
    9. }
     
    SubPixelPerfect likes this.
  4. Radu392

    Radu392

    Joined:
    Jan 6, 2016
    Posts:
    210
    What’s the use of a completely empty entity?
     
  5. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    they had components before, but all of them was removed at some point

    this is a good question

    yes, this is possible with chunk iteration, but is there a simple way?
     
  6. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    I don't know why but this whole conversation chain made me laugh out loud. Oh boy. :D
     
    utahrapter4 and SubPixelPerfect like this.
  7. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    the problem of entities who lost everything isn't a joke, this is a problem we need to solve together,
    if you have nothing to say better to donate a few spare components, or used buffer elements in good condition going to be very helpful as well
     
    starikcetin and utahrapter4 like this.
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    @SubPixelPerfect was that component with data, or with tag?

    For example, if I would have entity which suppose only to trigger some system, with single tag, or component, after job is done, remove entity, not the component.

    I tend to remove tags, but not components with data. Or create short living entities, which will be removed soon after.

    I avoid situation as fire, where entity become orphaned. Just thoughts.
     
    SubPixelPerfect likes this.
  9. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    To tell the truth this is not a real case, I've made it just out of curiosity to know if orphan get destroyed automatically. So the answer is they don't, and it is not that obvious how to cleanup them. So here I totally agree - it is better to avoid situation like this.
     
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    @SubPixelPerfect

    Don't know if is best option, but you could do checks, based on components count.
    Simply check, if entities are 0 components. Of course you need iterate all entities in this case, or at least already filtered out entities.

    Code (CSharp):
    1. EntityManager.GetComponentCount ( entity ) ;
     
  11. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    The easiest way of getting rid of entities with no components is:
    Code (CSharp):
    1.       Entities.ForEach((Entity e) => {
    2.         if (EntityManager.GetComponentCount(e) == 0)
    3.           PostUpdateCommands.DestroyEntity(e);
    4.       });
    Note that this generates garbage.
     
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    What if you have 100,000 components o_O That's a lot of iterations.
    I feel like sschoener is on the right track and it's easy to turn into a job.
     
    GilCat likes this.
  13. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Well. I didn't say it was performant. But then again there shouldn't be empty entities wondering around o_O
     
  14. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    I might be a little ignorant here, but what're the odds this is a chunk with a `SharedComponentData` still attached? It could even be some `SystemSharedComponentData` that isn't quite cleaned up.
     
  15. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Grabbing on what @sschoener wrote i've created a job for destroying empty entities:
    Code (CSharp):
    1.   [BurstCompile]
    2.   struct DestroyOnlyEntities : IJobChunk {
    3.     public EntityArchetype EntityOnlyArchetype;
    4.     [ReadOnly]
    5.     public ArchetypeChunkEntityType EntityType;
    6.     [WriteOnly]
    7.     public EntityCommandBuffer.Concurrent CmdBuffer;
    8.     public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
    9.       var entities = chunk.GetNativeArray(EntityType);
    10.       if (chunk.Archetype == EntityOnlyArchetype)    
    11.         for (var i = 0; i < chunk.Count; i++)
    12.           CmdBuffer.DestroyEntity(firstEntityIndex + i, entities[i]);
    13.     }
    14.   }
    When scheduling pass EntityManager.UniversalQuery as it's query.
    Note that it's even burstable because EntityCommandBuffer.DestroyEntity is supported by Burst.
     
    Last edited: Nov 27, 2019
    NotaNaN and Orimay like this.
  16. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    This solution doesn't work anymore on Entities 0.2.0 because EntityManager.GetEntityOnlyArchetype() was removed.
     
    NotaNaN likes this.
  17. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Actually you can use EntityManager.CreateArchetype() which is the same as our old EntityManager.GetEntityOnlyArchetype().
    So this works again :)
     
    MNNoxMortem likes this.