I am trying to acces entity component data in a parallel job. The component data is of type PheromoneComponent
. The struct that defines the job looks like this:
[UpdateBefore(typeof(PheromoneTrailsSystem))]
public class MovementSystem : JobComponentSystem
{
private EndSimulationEntityCommandBufferSystem endSimulationEntityCommandBuffer;
protected override void OnCreate()
{
endSimulationEntityCommandBuffer = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
base.OnCreate();
}
[BurstCompile]
struct MovementSpeedJob : IJobForEachWithEntity<Translation,Rotation, MovementComponent, QuadrantEntity, AntComponent>
{
[ReadOnly] public float dT;
[ReadOnly] public Unity.Mathematics.Random randGenerator;
[ReadOnly] public long currentTimestamp;
[ReadOnly] public int mapSizeHeight;
[ReadOnly] public int mapSizeWidth;
[ReadOnly] public NativeMultiHashMap<int, QuadrantData> quadrantMultiHashMap;
[ReadOnly] public ComponentDataFromEntity<PheromoneComponent> pheromoneDataArray;
//[NativeDisableParallelForRestriction] ComponentDataFromEntity<PheromoneComponent>
pheromoneDataArray;
public EntityCommandBuffer.Concurrent entityCommandBuffer;
public void Execute(Entity entity, int index, ref Translation translation, ref Rotation
rotation, ref MovementComponent movementComponent, ref QuadrantEntity quadrantEntity,
ref AntComponent antComponent){......}
The job is executed with the following instantiations:
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var job = new MovementSpeedJob()
{
dT = Time.deltaTime,
randGenerator = new
Unity.Mathematics.Random((uint)UnityEngine.Random.Range(1,100000)),
currentTimestamp = DateTime.Now.Ticks,
mapSizeHeight = GameState.GetMapSizeHeight(),
mapSizeWidth = GameState.GetMapSizeWidth(),
quadrantMultiHashMap = QuadrantSystem.quadrantMultiHashMap,
entityCommandBuffer =
endSimulationEntityCommandBuffer.CreateCommandBuffer().ToConcurrent(),
pheromoneDataArray = GetComponentDataFromEntity<PheromoneComponent>(true)
};
JobHandle jobHandle = job.Schedule(this, inputDeps);
endSimulationEntityCommandBuffer.AddJobHandleForProducer(jobHandle);
return jobHandle;
The code runs but I am getting the following error messages everytime update is called:
InvalidOperationException: The native container has been declared as [WriteOnly] in the job,
but you are reading from it.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) <0x1ba8eccc0 + 0x00052> in <85963591c1a04aad836445db604e7807>:0
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Jobs/AtomicSafetyHandle.bindings.cs:148)
Unity.Entities.ComponentJobSafetyManager.CompleteWriteDependency (System.Int32 type) (at Library/PackageCache/[email protected]/Unity.Entities/ComponentJobManager.cs:386)
Unity.Entities.EntityManager.GetComponentData[T] (Unity.Entities.Entity entity) (at Library/PackageCache/[email protected]/Unity.Entities/EntityManagerAccessComponentData.cs:42)
AntBehaviourSystem+ExcretionJob.Execute (Unity.Transforms.Translation& translation, Unity.Transforms.Rotation& rotation, QuadrantEntity& quadrantEntity, AntComponent& antComponent) (at Assets/Scripts/Ant/Systems/AntBehaviourSystem.cs:39)
Unity.Entities.JobForEachExtensions+JobStruct_Process_CCCC`5[T,T0,T1,T2,T3].ExecuteChunk (Unity.Entities.JobForEachExtensions+JobStruct_Process_CCCC`5[T,T0,T1,T2,T3]& jobData, System.IntPtr bufferRangePatchData, System.Int32 begin, System.Int32 end, Unity.Entities.ArchetypeChunk* chunks, System.Int32* entityIndices) (at Library/PackageCache/[email protected]/Unity.Entities/IJobForEach.gen.cs:3576)
Unity.Entities.JobForEachExtensions+JobStruct_Process_CCCC`5[T,T0,T1,T2,T3].Execute (Unity.Entities.JobForEachExtensions+JobStruct_Process_CCCC`5[T,T0,T1,T2,T3]& jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/[email protected]/Unity.Entities/IJobForEach.gen.cs:3541)
Since I never explicitly define the ComponentDataFromEntity
as [WriteOnly]
this error seems to say that there are some conflicts in the paralel job.
Am I even passing ComponentDataFromEntity
correctly?
Are there any other pitfalls that I am not aware of?
I have some other jobs that operate on PheromoneComponent
but i have tried disabeling them and the error persist. Also I guess the ECS job system should take care that all job dependancies are completed before executing another job.
I have also tried with [NativeDisableParallelForRestriction] ComponentDataFromEntity<PheromoneComponent>
instead of [ReadOnly] public ComponentDataFromEntity<PheromoneComponent> pheromoneDataArray;
but no change.
Any help or explanation will be greatly appreciated!
Edit (Solution): In my case, the issue was a conflict with a custom ReadOnly attribute I had in my project. I got rid of my custom attribute and everything works now.
I'm having the same issue and started a Unity forum thread, which has received as much attention as this question, sadly.
https://forum.unity.com/threads/readonly-errors-when-trying-to-use-componentdatafromentity.824799/
I'm starting to suspect that ComponentDataFromEntity just isn't supported inside ForEach jobs, but can't confirm it personally and don't know who can.