Crash when spawning an entity after destroying entities

I am new here and I have already spent some time looking a solution in this forum and examples, but I might have missed it.

I destroy entities when their age reach some threshold (this is temporary code to test things)

This code was extracted from the ECS examples, and it works. Entities are destroyed and disappear from the scene exactly as expected.

public partial class LifeTimeSystem : SystemBase
{
    EntityCommandBufferSystem ecbs;

    protected override void OnCreate()
    {
        ecbs = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
        //ecbs = World.GetOrCreateSystem<EndFixedStepSimulationEntityCommandBufferSystem>();
    }

    // OnUpdate runs on the main thread.
    protected override void OnUpdate()
    {
        var commandBuffer = ecbs.CreateCommandBuffer().AsParallelWriter();
        var deltaTime     = Time.DeltaTime;

        Dependency = Entities.ForEach((Entity entity, int nativeThreadIndex, ref CropState cropState) =>
        {
            cropState.age += deltaTime;

            if(cropState.age > 10.0f)
            {
                commandBuffer.DestroyEntity(nativeThreadIndex, entity);
            }

        }).ScheduleParallel(Dependency);

        ecbs.AddJobHandleForProducer(Dependency);
    }
}

Howerer, once any entity has been destroyed, instancing a new code triggers a crash with this message :

ArgumentException: All entities passed to EntityManager must exist. One of the entities has already been destroyed or was never created. EntitiesJournaling may be able to help determine more information. Please enable EntitiesJournaling for a more helpful error message.

New entities are instancied from monobehavior, one at a time, by the EntityManager.Instantiate method.

Where is my error?

Two things worth checking:
Use entityInQueryIndex for the ecb.DestroyEntity, not sure what happens if nativeThreadIndex is passed as a parameter.
https://docs.unity3d.com/Packages/com.unity.entities@0.51/api/Unity.Entities.EntityCommandBuffer.ParallelWriter.DestroyEntity.html#Unity_Entities_EntityCommandBuffer_ParallelWriter_DestroyEntity_System_Int32_Unity_Entities_Entity_

Timing & execution order:
MonoBehaviour execution order can be all over the frame, so the solution is to use an ECB to “queue up” whatever is needed to be created.

Alternatively, use a SystemBase system, iterate on MonoBehaviours and create entities when:

  • System is done running (in this case after EndSimulationECBSystem);
  • But before system starts to run again.

Usually I use two ECBSystems. One that adds entities, and another one destroys them. Execution order look like:
_ Frame start _

  • InstantiateECBSystem
  • DestroyECBSystem
  • BeginSimECBSystem
  • EndSimECBSystem

This also ensures that ECB.RemoveComponentForEntityQuery runs on the correct set of entities.

As a side note, you don’t need to manually set Dependency if ForEach is used. Codegen will automatically combine it.

@stephc-int13 , you passing nativeThreadIndex instead of entityInQueryIndex to EntityCommandBuffer