Search Unity

Question NullReferenceException in ArchetypeChunk when scheduling an IJobEntityBatchWithIndex

Discussion in 'Entity Component System' started by welcometoland, Dec 1, 2021.

  1. welcometoland

    welcometoland

    Joined:
    Jan 8, 2020
    Posts:
    1
    hi,

    I'm trying to change the number of batches when scheduling an IJobEntityBatchWithIndex.
    Goal is to run an expansive job in parralel over a small number of chunk and entities.
    However, when I change the number of batchesPerChunk for a number > 1, I get the following error :


    NullReferenceException: Object reference not set to an instance of an object
    Unity.Entities.ArchetypeChunk.get_Count () (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/Iterators/ArchetypeChunkArray.cs:34)
    Unity.Entities.JobEntityBatchIndexExtensions+JobEntityBatchIndexProducer`1[T].ExecuteInternal (Unity.Entities.JobEntityBatchIndexExtensions+JobEntityBatchIndexWrapper`1[T]& jobWrapper, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobEntityBatchWithIndex.cs:587)
    Unity.Entities.JobEntityBatchIndexExtensions+JobEntityBatchIndexProducer`1[T].Execute (Unity.Entities.JobEntityBatchIndexExtensions+JobEntityBatchIndexWrapper`1[T]& jobIndexWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobEntityBatchWithIndex.cs:558)


    My guess is something to deal with the archetype modification (RemoveComponent)
    Does anyone have an idea of how I can avoid this error ? maybe it's a dependencies issues ?

    Here, a simple example of how reproduce my issue.

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3.  
    4. public class Example : MonoBehaviour
    5. {
    6.     private Entity[] entities;
    7.     private int entityCount = 10;
    8.     private EntityManager em;
    9.     void Start()
    10.     {
    11.         entities = new Entity[entityCount];
    12.         em = World.DefaultGameObjectInjectionWorld.EntityManager;
    13.         for (int i = 0; i < entityCount; i++)
    14.         {
    15.             entities[i] = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity();
    16.             em.AddComponent<IsActive>(entities[i]);
    17.         }
    18.     }
    19.     void Update()
    20.     {
    21.         int randomIndex = Random.Range(0, entityCount - 1);
    22.         // remove one entity of the archetype
    23.         em.RemoveComponent<IsActive>(entities[randomIndex]);
    24.     }
    25. }
    26.  
    27. public struct IsActive : IComponentData { }
    28.  
    29.  
    30. public class MySystem : SystemBase
    31. {
    32.     private BeginSimulationEntityCommandBufferSystem ecbSystem;
    33.     private EntityQueryDesc entityQueryDesc;
    34.     private EntityQuery entityQuery;
    35.    
    36.     protected override void OnCreate()
    37.     {
    38.         ecbSystem = World.GetOrCreateSystem<BeginSimulationEntityCommandBufferSystem>();
    39.         base.OnCreate();
    40.  
    41.         entityQueryDesc = new EntityQueryDesc
    42.         {
    43.             All = new ComponentType[] { typeof(IsActive) }
    44.         };
    45.  
    46.         entityQuery = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntityQuery(entityQueryDesc);    
    47.     }
    48.  
    49.     protected override void OnUpdate()
    50.     {
    51.         Debug.Log(entityQuery.CalculateChunkCount());
    52.         Debug.Log(entityQuery.CalculateEntityCount());
    53.  
    54.         var job = new MyVeryExpansiveJob();
    55.  
    56.         this.Dependency = job.ScheduleParallel(entityQuery, 4, this.Dependency);
    57.         ecbSystem.AddJobHandleForProducer(this.Dependency);
    58.     }
    59. }
    60.  
    61.  
    62. public struct MyVeryExpansiveJob : IJobEntityBatchWithIndex
    63. {
    64.     public void Execute(ArchetypeChunk batchInChunk, int batchIndex, int indexOfFirstEntityInQuery)
    65.     {
    66.         // nothing particular
    67.     }
    68. }
    I'm using unity.entities 0.17.0-preview42

    thank you in advance !
     
    guillaume-t likes this.
  2. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    966
    I got the same error when I tried with a batchCount > 1. Think it's just bugged.
     
    Tony_Max and welcometoland like this.
  3. guillaume-t

    guillaume-t

    Joined:
    Feb 4, 2021
    Posts:
    1
    I have encountered the same bug and your code sample reproduces it indeed.
    I may have fixed it as follow :

    Code (CSharp):
    1.  
    2. public struct MyVeryExpansiveJob : IJobParallelFor
    3. {
    4.     public ArchetypeChunk chunk;
    5.     public void Execute(int index)
    6.     {
    7.         // nothing particular
    8.     }
    9. }
    And in MySystem :

    Code (CSharp):
    1. protected override void OnUpdate()
    2.     {
    3.         Debug.Log(entityQuery.CalculateChunkCount());
    4.         Debug.Log(entityQuery.CalculateEntityCount());
    5.  
    6.         NativeArray<ArchetypeChunk> chunkArchetypes = GetEntityQuery(typeof(IsActive)).CreateArchetypeChunkArray(Unity.Collections.Allocator.Temp);
    7.  
    8.         int nbatch = 1;
    9.         foreach (ArchetypeChunk chunk in chunkArchetypes) {
    10.             new MyVeryExpansiveJob() {
    11.                 chunk = chunk
    12.             }.Schedule(chunk.ChunkEntityCount, chunk.ChunkEntityCount/nbatch);
    13.         }
    14.         chunkArchetypes.Dispose();
    15.     }
    nbatch is the number of batch that you want, to match your sample code you would set it to 4.
     
  4. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    353
    Same. This helps!