- Home /
Acessing static variable from Entities.ForEach
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()
{
Debug.Log(QuadrantSystem.quadrantMultiHashMap.Count());
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?
Answer by SirDodgy · May 14, 2020 at 03:26 PM
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 SystemBase 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.