Errors when instantiating and destroying entities in different jobsystems

Hi all,

I have essentially two systems, one which creates entities in a job and the other which destroys those entities under given conditions. I am using Unity 2019.1.0b6.

This seems to work fine for small numbers, but as the number of entities being spawned and destroyed increases, numerous errors start to appear.

These entities are not being created or destroyed in any other location, although their translation is being updated in the second system.

Here are some of the errors I am seeing:

Error 1

ArgumentException: Invalid command buffer
EntityCommandBuffer was recorded in MoveProjectileSystem and played back in Unity.Entities.EndSimulationEntityCommandBufferSystem.
at Unity.Entities.EntityCommandBuffer.PlaybackChain (Unity.Entities.EntityManager mgr, Unity.Entities.ECBSharedPlaybackState& playbackState, Unity.Collections.NativeArray`1[T] chainStates, System.Int32 currentChain, System.Int32 nextChain) [0x0046c] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:1154

at Unity.Entities.EntityCommandBuffer.Playback (Unity.Entities.EntityManager mgr) [0x0025d] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:943

at Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) [0x00048] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\ComponentSystem.cs:799
Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:851)
Unity.Entities.EntityCommandBufferSystem.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:773)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ComponentSystemGroup.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystemGroup.cs:264)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelegateWrapper.TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourUpdateOrder.cs:132)

Error 2

ArgumentException: Object reference not set to an instance of an object
EntityCommandBuffer was recorded in MoveProjectileSystem and played back in Unity.Entities.EndSimulationEntityCommandBufferSystem.
at Unity.Entities.EntityCommandBuffer.PlaybackChain (Unity.Entities.EntityManager mgr, Unity.Entities.ECBSharedPlaybackState& playbackState, Unity.Collections.NativeArray`1[T] chainStates, System.Int32 currentChain, System.Int32 nextChain) [0x00042] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:1016

at Unity.Entities.EntityCommandBuffer.Playback (Unity.Entities.EntityManager mgr) [0x0025d] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:943

at Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) [0x00048] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\ComponentSystem.cs:799
Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:851)
Unity.Entities.EntityCommandBufferSystem.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:773)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ComponentSystemGroup.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystemGroup.cs:264)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelegateWrapper.TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourUpdateOrder.cs:132)

Error 3

Assertion failure. Value was False

Expected: True
UnityEngine.Assertions.Assert:IsTrue(Boolean)
Unity.Assertions.Assert:IsTrue(Boolean) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/Stubs/Unity.Assertions/Assert.cs:15)
Unity.Entities.EntityCommandBuffer:PlaybackChain(EntityManager, ECBSharedPlaybackState&, NativeArray`1, Int32, Int32) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/EntityCommandBuffer.cs:1014)
Unity.Entities.EntityCommandBuffer:Playback(EntityManager) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/EntityCommandBuffer.cs:943)
Unity.Entities.EntityCommandBufferSystem:FlushBuffers(Boolean) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:799)
Unity.Entities.EntityCommandBufferSystem:OnUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:773)
Unity.Entities.ComponentSystem:InternalUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager:Update() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystemGroup.cs:264)
Unity.Entities.ComponentSystem:InternalUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager:Update() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourUpdateOrder.cs:132)

Error 4

Assertion failure. Values are not equal.

Expected: 1 == 2
UnityEngine.Assertions.Assert:AreEqual(Int32, Int32)
Unity.Assertions.Assert:AreEqual(Int32, Int32) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/Stubs/Unity.Assertions/Assert.cs:66)
Unity.Entities.EntityCommandBuffer:Playback(EntityManager) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/EntityCommandBuffer.cs:915)
Unity.Entities.EntityCommandBufferSystem:FlushBuffers(Boolean) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:799)
Unity.Entities.EntityCommandBufferSystem:OnUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:773)
Unity.Entities.ComponentSystem:InternalUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager:Update() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystemGroup.cs:264)
Unity.Entities.ComponentSystem:InternalUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager:Update() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourUpdateOrder.cs:132)

The entities are being created in this system:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Collections;
using Unity.Jobs;


public class ShootingSystem : JobComponentSystem
{
    EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;

    ComponentGroup m_Positions;
    ComponentGroup m_ProjectileSpawner;

    public struct SpawnProjectileJob : IJobProcessComponentDataWithEntity<FriendlyUnit, Weapon, Translation>
    {
        [ReadOnly] public EntityCommandBuffer CommandBuffer;
        [ReadOnly, DeallocateOnJobCompletion] public NativeArray<HelloSpawner> spawner;

        public void Execute(Entity entity, int index, [ReadOnly] ref FriendlyUnit fU, ref Weapon w, ref Translation t)
        {
            if (w.gotTarget == 1)
            {
                if (w.firingTimer == 0)
                {
                    // FIRE!
                    var instance = CommandBuffer.Instantiate(spawner[0].Prefab);
                    Projectile projectile = new Projectile
                    {
                        dst = w.targetEntity,
                        speed = w.projectileSpeed,     
                    };
                    CommandBuffer.SetComponent(instance, projectile);
                    CommandBuffer.SetComponent(instance, t);

                    //reset firing counter
                    w.firingTimer = w.firingRate;
                }
                else
                    w.firingTimer--;
            }
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var spawner = m_ProjectileSpawner.ToComponentDataArray<HelloSpawner>(Allocator.TempJob);

        var spawnjob = new SpawnProjectileJob
        {
            CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer(),
            spawner = spawner,
        }.Schedule(this, inputDeps);

        m_EntityCommandBufferSystem.AddJobHandleForProducer(spawnjob);

        return spawnjob;
    }


    protected override void OnCreateManager()
    {
        m_EntityCommandBufferSystem = World.GetOrCreateManager<EndSimulationEntityCommandBufferSystem>();
        m_Positions = GetComponentGroup(typeof(Translation));
        m_ProjectileSpawner = GetComponentGroup(typeof(HelloSpawner), typeof(LocalToWorld));

       
    }
}

And the entities are destroyed in this system:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Collections;
using Unity.Jobs;


public class MoveProjectileSystem : JobComponentSystem
{
    EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
  

    public struct MoveProjectile : IJobProcessComponentDataWithEntity<Projectile, Translation>
    {
        [ReadOnly] public EntityCommandBuffer CommandBuffer;

        [ReadOnly] public ComponentDataFromEntity<LocalToWorld> localToWorld;

        public void Execute(Entity entity, int index, ref Projectile p, ref Translation t)
        {
            Vector3 currentPos = t.Value;
   
            Vector3 dstPos;
            // hacky way to get around the entitiy created by the ConvertToEntity script
            //if (p.dst.Index == 0)
            //    return;
            dstPos = localToWorld[p.dst].Value.c3.xyz;

            Vector3 newPos = Vector3.MoveTowards(currentPos, dstPos, p.speed);
            t.Value = newPos;
            float dist = math.distance(currentPos, dstPos);

            if (dist < 1)
            {
                // HIT!
                CommandBuffer.DestroyEntity(entity);
            }
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var positions = GetComponentDataFromEntity<LocalToWorld>();
        var movejob = new MoveProjectile
        {
            CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer(),
            localToWorld = positions,
        }.Schedule(this, inputDeps);

        m_EntityCommandBufferSystem.AddJobHandleForProducer(movejob);

        return movejob;
    }

    protected override void OnCreateManager()
    {
        m_EntityCommandBufferSystem = World.GetOrCreateManager<EndSimulationEntityCommandBufferSystem>();    
    }
}

I get the feeling the two jobsystems are conflicting when one is trying to add entities and the other is trying to read these entities and remove them conditionally.

Add [UpdaterAfter(typeof(ShootingSystem))] on Shooting system. See what happen.
Maybe because MoveProjectileSystem call Destroy Entity before shooting system set component on it

I believe you mean add [UpdateAfter(typeof(ShootingSystem))] on MoveProjectileSystem.

Either way, it hasnt resolved the issue.

I am now getting a different error:

Error 5

ArgumentException: All entities passed to EntityManager must exist. One of the entities has already been destroyed or was never created.
EntityCommandBuffer was recorded in MoveProjectileSystem and played back in Unity.Entities.EndSimulationEntityCommandBufferSystem.
at Unity.Entities.EntityDataManager.AssertEntitiesExist (Unity.Entities.Entity* entities, System.Int32 count) [0x00081] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityDataManager.cs:341

at Unity.Entities.EntityManager.AddComponent (Unity.Entities.Entity entity, Unity.Entities.ComponentType componentType) [0x00008] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityManager.cs:477

at Unity.Entities.EntityCommandBuffer.PlaybackChain (Unity.Entities.EntityManager mgr, Unity.Entities.ECBSharedPlaybackState& playbackState, Unity.Collections.NativeArray`1[T] chainStates, System.Int32 currentChain, System.Int32 nextChain) [0x002b8] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:1096

at Unity.Entities.EntityCommandBuffer.Playback (Unity.Entities.EntityManager mgr) [0x0025d] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\EntityCommandBuffer.cs:943

at Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) [0x00048] in D:\Unity Projects\RTS_SciFi\Library\PackageCache\com.unity.entities@0.0.12-preview.26\Unity.Entities\ComponentSystem.cs:799
Unity.Entities.EntityCommandBufferSystem.FlushBuffers (System.Boolean playBack) (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:851)
Unity.Entities.EntityCommandBufferSystem.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:773)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ComponentSystemGroup.OnUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystemGroup.cs:264)
Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ComponentSystem.cs:479)
Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourManager.cs:97)
Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelegateWrapper.TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.26/Unity.Entities/ScriptBehaviourUpdateOrder.cs:132)

I’m wondering whether its something to do with the CommandBufferSystem.

From what I can see there are several of these and I have no idea what the difference between them is:

Can anyone explain the difference between these?

Unity has updated the number of built-in syncpoints to start building a better game loop for ECS. They’ve renamed BarrierSystem to EntityCommandBufferSystem, to better clarify it’s association with EntityCommandBuffers.

They removed the old EndFrameBarrierSystem and these are the replacements, each having a different purpose:

Begin/End InitializationEntityCommandBufferSystem are used during bootstrap/startup phase.

Begin/End Simulation are during simulation step, eventually this will replace Fixed Update.

Begin/End Presentation are intended to run after physics and animation have run, eventually this will replace Update.

Each of these phases is run as part of a Group system, which can be used to manually update a set of Systems as well as group related systems together. This replaces the older more confusing system group type association, allows for more manual setup, and will eventually lead to things like iterative physics loops and solver-type systems.

You can manually add your systems to any phase and use the Begin/End ECBSystems as sync points. By default, Systems will be added to the Simulation group if not marked as DisableAutoCreation.

More info can be found in this thread, including the rationale: Why is Simulation the default system group?

2 Likes

@Init33 Did you found solution?