Search Unity

Editor causing ECS crash

Discussion in 'Entity Component System' started by Srokaaa, Oct 23, 2018.

  1. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    I get a crash that seems to be dependent on the way that the code is run in the Editor.

    When I click Play the first time my game runs just fine. When I stop the game and run it a second time it crashes when I try to call CreateEntity on EntityCommanBuffer:


    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. Unity.Entities.ComponentChunkIterator.UpdateCacheToCurrentChunk (Unity.Entities.ComponentChunkCache& cache, System.Boolean isWriting, System.Int32 indexInComponentGroup) (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/Iterators/ComponentChunkIterator.cs:368)
    3. Unity.Entities.ComponentChunkIterator.MoveToEntityIndexAndUpdateCache (System.Int32 index, Unity.Entities.ComponentChunkCache& cache, System.Boolean isWriting) (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/Iterators/ComponentChunkIterator.cs:387)
    4. Unity.Entities.EntityArray.get_Item (System.Int32 index) (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/Iterators/EntityArray.cs:46)
    5. ECS.Systems.Board.BoardAttachSystem.OnUpdate () (at Assets/Scripts/ECS/Systems/Board/BoardAttachSystem.cs:30)
    6. Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/ComponentSystem.cs:374)
    7. Unity.Entities.ScriptBehaviourManager.Update () (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/ScriptBehaviourManager.cs:77)
    8. Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelagateWrapper.TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/ScriptBehaviourUpdateOrder.cs:703)
    9.  
    This will happen over and over again until i restart Unity. Changing the scenes doesn't help
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,258
    I ran into this issue too, although in a totally different use case from an EntityCommandBuffer.

    This code breaks after the first run:

    Code (CSharp):
    1. public Entity GetFirstEntity(ComponentGroup group)
    2.         {
    3.             var entities = group.GetEntityArray();
    4.             if (entities.Length <= 0)
    5.             {
    6.                 throw new InvalidOperationException($"Failed to find an entity in {group}");
    7.             }
    8.             return entities[0];
    9.         }
    This alternative code works pretty consistently:
    Code (CSharp):
    1. public Entity GetFirstEntity(ComponentGroup group)
    2.         {
    3.             if (group.CalculateLength() <= 0)
    4.             {
    5.                 throw new InvalidOperationException($"Failed to find an entity in {group}");
    6.             }
    7.  
    8.             var entityType = GetArchetypeChunkEntityType();
    9.             var chunks = group.CreateArchetypeChunkArray(Allocator.Temp);
    10.             var entities = chunks[0].GetNativeArray(entityType);
    11.             var entity = entities[0];
    12.             chunks.Dispose();
    13.             return entity;
    14.         }
    EntityArray seems to be the culprit. Note that I am using a custom world and manually creating and updating systems.
     
  3. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @DreamingImLatios Uh, yes, I forgot to add this. I was using ComponentGroups. Today I moved all of my systems to using [Inject] and everything works fine.
     
  4. psuong

    psuong

    Joined:
    Jun 11, 2014
    Posts:
    126
  5. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @psuong That's why I was using ComponentGroups in the first place. Once we get a properly working alternative I'll move from [Inject]. Translating between [Inject] method and ComponentGroups is pretty straightforward
     
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    CG and Chunk Iteration works perfectly, and I think problem in your logic, but without any context no one can help to solve it :)
     
  7. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @eizenhorn See the code example in the second comment ( by @DreamingImLatios ). The exact same thing is happening for me. Whenever I use ComponentGroup.GetEntityArray() I get crashes on EntityCommandBuffer.CreateEntity() in a subsequent launches in GameMode
     
  8. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Again - there is NO some context.
    Just for show you, write simple system which creates command buffers and gets entities array from group many times.

    Code (CSharp):
    1. public struct SomeComponent : IComponentData
    2. {
    3.     public int Value;
    4. }
    5.  
    6. [AlwaysUpdateSystem]
    7. public class TestSystem : JobComponentSystem
    8. {
    9.     private ComponentGroup someGroup;
    10.     private TestSystemBarrier barrier;
    11.  
    12.     protected override void OnCreateManager()
    13.     {
    14.         barrier = World.GetOrCreateManager<TestSystemBarrier>();
    15.         someGroup = GetComponentGroup(typeof(SomeComponent));
    16.     }
    17.  
    18.     public struct TestParallelJob : IJobParallelFor
    19.     {
    20.         public EntityCommandBuffer.Concurrent ecb;
    21.  
    22.         public void Execute(int index)
    23.         {
    24.             ecb.CreateEntity(index);
    25.             ecb.AddComponent(index, new SomeComponent()
    26.             {
    27.                 Value = index
    28.             });
    29.         }
    30.     }
    31.  
    32.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    33.     {
    34.         if (Input.GetKeyDown(KeyCode.Space))
    35.         {
    36.             inputDeps.Complete();
    37.  
    38.             Debug.Log("Check entity array exists");
    39.             EntityArray entities = someGroup.GetEntityArray();
    40.             if (entities.Length == 0)
    41.             {
    42.                 Debug.Log("Entities not wxists. Create 10 entities from parallel job!");
    43.                 TestParallelJob job = new TestParallelJob()
    44.                 {
    45.                     ecb = barrier.CreateCommandBuffer().ToConcurrent()
    46.                 };
    47.                 job.Schedule(10, 10).Complete();
    48.             }
    49.             else
    50.             {
    51.                 Debug.Log($"{entities.Length} entities exists! Try get entities again!");
    52.                 EntityArray entities2 = someGroup.GetEntityArray();
    53.                 Debug.Log($"And again {entities2.Length} exists!");
    54.             }
    55.      
    56.         }
    57.  
    58.         return inputDeps;
    59.     }
    60. }
    All works as expected, after first run, second run and other. With check on space pressed,
    upload_2018-10-26_16-0-39.png

    without check space pressed (logging every frame)
    upload_2018-10-26_16-8-58.png

    Also all works fine if create system manually
    Code (CSharp):
    1. public class TestSystem : MonoBehaviour
    2. {
    3.     private TestJobSystem _jobsystem;
    4.  
    5.     private void Update()
    6.     {
    7.         if (Input.GetKeyDown(KeyCode.C))
    8.         {
    9.             _jobsystem = World.Active.GetOrCreateManager<TestJobSystem>();
    10.             ScriptBehaviourUpdateOrder.UpdatePlayerLoop(World.Active);
    11.         }
    12.     }
    13. }
    14.  
    15. public struct SomeComponent : IComponentData
    16. {
    17.     public int Value;
    18. }
    19.  
    20. [DisableAutoCreation, AlwaysUpdateSystem]
    21. public class TestJobSystem : JobComponentSystem
    22. {
    23.     private ComponentGroup _someGroup;
    24.     private TestJobSystemBarrier _barrier;
    25.  
    26.     protected override void OnCreateManager()
    27.     {
    28.         Debug.Log("Created!");
    29.         _barrier = World.GetOrCreateManager<TestJobSystemBarrier>();
    30.         _someGroup = GetComponentGroup(typeof(SomeComponent));
    31.     }
    32.  
    33.     public struct TestParallelJob : IJobParallelFor
    34.     {
    35.         public EntityCommandBuffer.Concurrent ecb;
    36.  
    37.         public void Execute(int index)
    38.         {
    39.             ecb.CreateEntity(index);
    40.             ecb.AddComponent(index, new SomeComponent()
    41.             {
    42.                 Value = index
    43.             });
    44.         }
    45.     }
    46.  
    47.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    48.     {
    49.         inputDeps.Complete();
    50.  
    51.         Debug.Log("Check entity array exists");
    52.         EntityArray entities = _someGroup.GetEntityArray();
    53.         if (entities.Length == 0)
    54.         {
    55.             Debug.Log("Entities not wxists. Create 10 entities from parallel job!");
    56.             TestParallelJob job = new TestParallelJob()
    57.             {
    58.                 ecb = _barrier.CreateCommandBuffer().ToConcurrent()
    59.             };
    60.             job.Schedule(10, 10).Complete();
    61.         }
    62.         else
    63.         {
    64.             Debug.Log($"{entities.Length} entities exists! Try get entities again!");
    65.             EntityArray entities2 = _someGroup.GetEntityArray();
    66.             Debug.Log($"And again {entities2.Length} exists!");
    67.         }
    68.  
    69.         return inputDeps;
    70.     }
    71. }
    72.  
    73. [UpdateAfter(typeof(TestJobSystem))]
    74. public class TestJobSystemBarrier : BarrierSystem
    75. {
    76.  
    77. }
    upload_2018-10-26_16-44-16.png
     
    Last edited: Nov 13, 2018
  9. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,258
    The errors come from indexing EntityArray using the index operator [].
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    No. Indexing works fine.

    upload_2018-10-27_7-58-3.png

    And all works as expected without errors after many Play\Unplay loops upload_2018-10-27_7-59-48.png
     
  11. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @eizenhorn Yeah, you're right. I'll try to provide a repo with a minimal project reproducing the crash this weekend