I’m getting an error trying to write to an entity’s dynamicBuffer from within an IJob : “InvalidOperationException: The native container has been declared as [ReadOnly] in the job, but you are writing to it.”
I’m confused, I don’t think I’m declaring it as readonly.
This is the offending line :
woodCutterBuffer.Add(new WoodCutterBufferElement { Value = woodCutterEntity });
public struct ProcessUnAssignedWoodCutters : IJob
{
[ReadOnly]
[DeallocateOnJobCompletion]
public NativeArray<ArchetypeChunk> unAssignedWoodCutters;
[DeallocateOnJobCompletion]
public NativeArray<ArchetypeChunk> woodCutterBuildingChunks;
public ArchetypeChunkBufferType<WoodCutterBufferElement> woodCutterBufferType;
public ArchetypeChunkComponentType<WoodCutterBuilding> woodCutterBuildingType;
[ReadOnly]
public ArchetypeChunkEntityType entityType;
public EntityCommandBuffer buffer;
public void Execute()
{
for (var i = 0; i < unAssignedWoodCutters.Length; i++)
{
var chunk = unAssignedWoodCutters[i];
var chunkCount = chunk.Count;
var woodCutterEntities = chunk.GetNativeArray(entityType);
for (var j = 0; j < chunkCount; j++)
{
var woodCutterEntity = woodCutterEntities[j];
for (var x = 0; x < woodCutterBuildingChunks.Length; x++)
{
var buildingChunk = woodCutterBuildingChunks[x];
var buildingChunkCount = buildingChunk.Count;
var buildingWoodCutterBuffers = buildingChunk.GetBufferAccessor(woodCutterBufferType);
var buildingDataArray = buildingChunk.GetNativeArray(woodCutterBuildingType);
for (var y = 0; y < buildingWoodCutterBuffers.Length; y++)
{
var woodCutterBuffer = buildingWoodCutterBuffers[y];
var buildingData = buildingDataArray[y];
if (woodCutterBuffer.Length == buildingData.maxWorkers)
{
continue;
}
woodCutterBuffer.Add(new WoodCutterBufferElement { Value = woodCutterEntity });
buffer.RemoveComponent(woodCutterEntity, typeof(NotAssignedToBuilding));
}
}
}
}
}
}
private JobHandle ScheduleUnAssignedWorkersJob(JobHandle inputDeps)
{
var entityType = EntityManager.GetArchetypeChunkEntityType();
// process un-assigned woodcutters
var unassignedWoodCuttersQuery = new EntityArchetypeQuery
{
Any = new ComponentType[0],
None = new ComponentType[0],
All = new ComponentType[] { typeof(WoodCutterOccupation), typeof(NotAssignedToBuilding) }
};
var woodCutterBuildingQuery = new EntityArchetypeQuery
{
Any = new ComponentType[0],
None = new ComponentType[0],
All = new ComponentType[] { typeof(WoodCutterBuilding) }
};
woodCutterBuildingChunks = EntityManager.CreateArchetypeChunkArray(woodCutterBuildingQuery, Allocator.TempJob);
unassignedWoodCutterChunks = EntityManager.CreateArchetypeChunkArray(unassignedWoodCuttersQuery, Allocator.TempJob);
var woodCutterBuildingBufferType = EntityManager.GetArchetypeChunkBufferType<WoodCutterBufferElement>(false);
var woodCutterBuildingType = EntityManager.GetArchetypeChunkComponentType<WoodCutterBuilding>(false);
var processUnAssignedWoodCuttersJob = new ProcessUnAssignedWoodCutters
{
unAssignedWoodCutters = unassignedWoodCutterChunks,
woodCutterBuildingChunks = woodCutterBuildingChunks,
woodCutterBufferType = woodCutterBuildingBufferType,
woodCutterBuildingType = woodCutterBuildingType,
buffer = unassignedWorkersBarrier.CreateCommandBuffer(),
entityType = entityType
};
return processUnAssignedWoodCuttersJob.Schedule(inputDeps);
}
[InternalBufferCapacity(8)]
public struct WoodCutterBufferElement : IBufferElementData
{
// These implicit conversions are optional, but can help reduce typing.
public static implicit operator Entity(WoodCutterBufferElement e) { return e.Value; }
public static implicit operator WoodCutterBufferElement(Entity e) { return new WoodCutterBufferElement { Value = e }; }
// Actual value each buffer element will store.
public Entity Value;
}