EntityManager.Exists returns true after Entity was destroyed?

So I have a ComponentSystem that destroys Entities and one that checks components on Entities. The destroy-System runs shortly before the check-System (but both are ComponentSystems, so both on the Main Thread, right?)

Now when I am checking the Components of an Entity that was destroyed the same frame, EntityManager.Exists returns true, but the Component of the Entity I am trying to access already got removed, so I get an ArgumentException: A component with type:Translation has not been added to the entity.

Is this a bug or are there some multithreaded/other things going on that have to be kept in mind when using EntityManager.Exists?

(Using Entities 0.5.0)

Code:

// Runs first
public class DeathSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        Entities.ForEach((Entity e, ref Health health) =>
        {
            if (health.Value <= 0)
            {
                Debug.Log("Entity Died: " + e);
                EntityManager.DestroyEntity(e);
                // Same result with PostUpdateCommands.DestroyEntity(e)
            }
        });
    }
}
// Runs second
public class DummyKISystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        Entities.ForEach((ref DummyKIComponent dummy, ref Translation translation, ref Rotation rotation, ref MovementSpeed speed) =>
        {
            if (dummy.CurrentTarget == Entity.Null)
            {
                ...
            }
            else if (!EntityManager.Exists(dummy.CurrentTarget))
                dummy.CurrentTarget = Entity.Null;
            else
            {                
                if (!EntityManager.HasComponent<Translation>(dummy.CurrentTarget))
                    Logger.Log("Blargh! " + dummy.CurrentTarget);
                // ... (Access Translation Component)
            }
        });
    }
}

Result:
5391270--546759--upload_2020-1-20_23-7-50.png

I unfortunately don’t have a solution, but did you omit or forget a [UpdateBefore(typeof(DeathSystem))] for DummyKISystem? I don’t know about ForEach but PostUpdateCommands is definitely run on the main thread, sequentially, per the official Command Buffer docs.

To remove the possibility of a race condition, I made just one system:

public class TestComponentSystem : ComponentSystem {

    protected override void OnUpdate()
    {
        int n = 0;
        Entities.ForEach((Entity e) =>
        {
            UnityEngine.Debug.Log(EntityManager.Exists(e));
            PostUpdateCommands.DestroyEntity(e);
            n++;
        });
        UnityEngine.Debug.Log(n);
    }
}

The output is consistent with yours though – the entity is, oddly enough, never destroyed. (The system continues to iterate over the same entities, even after the update function completes and the next frame is run)

I am having the same problem, did you find a solution?

I would think that the second system would implicitly create a entity query in the lambda so that you don’t have to use the EntiyManager inside the function.

Turns out there are types of Components, which can keep an Entity alive after destroying it:
https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/system_state_components.html

In my case it was a GhostSystemStateComponent from the NetCode Package.
I guess in these cases we have to do a HasComponent check to be completely sure.

2 Likes