You must call JobHandle.Complete() on the job QuadrantSystem

I’m trying to create a grid map of my entities’ positions

I’m trying to use entities.foreach to grab position data from entities and update a multi hash map like this:

public class QuadrantSystem : JobComponentSystem
    {
        private EntityQuery query;
 
        public static NativeMultiHashMap<int, SectorData> quadrantMultiHashMap;
 
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        { 
            quadrantMultiHashMap.Clear();
            if (query.CalculateEntityCount() > quadrantMultiHashMap.Capacity)
            {
                quadrantMultiHashMap.Capacity = query.CalculateEntityCount();
            }
 
            var LquadrantMultiHashMap = quadrantMultiHashMap.AsParallelWriter();
            JobHandle hashJobHandle = Entities
                .ForEach((Entity entity, int entityInQueryIndex, in Translation translation) =>
                {
                    int hashMapKey = GetPositionHashMapKey(translation.Value);
                    LquadrantMultiHashMap.Add(hashMapKey, new SectorData
                    {
                        entity = entity,
                        position = translation.Value
                    });
                })
               .WithStoreEntityQueryInField(ref query)
               .Schedule(inputDeps);
 
            return hashJobHandle;
        }

And access it in another system like this:

[UpdateAfter(typeof(QuadrantSystem))]
    public class WorldRenderer : ComponentSystem
    {
        protected override void OnUpdate()
        {

        NativeMultiHashMap<int, SectorData> quadrantMultiHashMap = QuadrantSystem.quadrantMultiHashMap;
        Debug.Log(quadrantMultiHashMap.Count().ToString());

However unity throws an invalid operation:

Which says " You must call JobHandle.Complete() on the job QuadrantSystem, before you can read from the Unity.Collections.NativeMultiHashMap". However I would have thought [UpdateAfter(typeof(QuadrantSystem))] would solve this problem no?

What am I doing wrong?

Ok I figured it out. The error actually showed the answer. I needed to call JobHandle.Complete() on the job. Here my entire class, updated with using basesystem instead of JobComponentSystem

public struct SectorData
{
    public Entity entity;
    public float3 position;
}

//[DisableAutoCreation]
public class QuadrantSystem : SystemBase
{
    private EntityQuery query;

    public static NativeMultiHashMap<int, SectorData> quadrantMultiHashMap;

    public const int quadrantYMultiplier = LevelGeneration.GridLength;
    private const int quadrantCellSize = LevelGeneration.GridWorldSize;

    public static int GetPositionHashMapKey(float3 position)
    {
        return (int)(math.floor(position.x / quadrantCellSize) + (quadrantYMultiplier * math.floor(position.y / quadrantCellSize)));
    }

    protected override void OnCreate()
    {
        quadrantMultiHashMap = new NativeMultiHashMap<int, SectorData>(0, Allocator.Persistent);
        base.OnCreate();
    }

    protected override void OnDestroy()
    {
        quadrantMultiHashMap.Dispose();
        base.OnDestroy();
    }

    protected override void OnUpdate()
    {
        quadrantMultiHashMap.Clear();
        if (query.CalculateEntityCount() > quadrantMultiHashMap.Capacity)
        {
            quadrantMultiHashMap.Capacity = query.CalculateEntityCount();
        }

        var LquadrantMultiHashMap = quadrantMultiHashMap.AsParallelWriter();

        Entities.ForEach((Entity entity, int entityInQueryIndex, in Translation translation) =>
        {
            int hashMapKey = GetPositionHashMapKey(translation.Value);
            LquadrantMultiHashMap.Add(hashMapKey, new SectorData
            {
                entity = entity,
                position = translation.Value
            });
        })
        .WithStoreEntityQueryInField(ref query)
        .ScheduleParallel();

        this.CompleteDependency();
    }
}

With basesystem you call this.CompleteDependency(); instead of calling .Complete() on the job.

5 Likes