Hello,
I have a noob problem I knew how to solve in SystemBase, but not in ISystem
Basically:
- I have an hexagonal grid map.
- Each hexagon has a Dynamic Buffer with 729 values describing the map within.
- These maps are generated and modified at runtime.
- I need a system that can iterate over every hexagon’s buffer and apply changes following the same formulas, as needed.
In SystemBase, I could give a NativeArray with the property (.WithNativeDisableParallelWriting(NativeArray)" or something like that, and I could read and write in parallel to my heart’s content.
How can I do this from an ISystem?
Thank you for your time (I’m currently watching Codemonkey’s free ecs course, hopefully the answer will appear there, as it has solved other questions I had already)
I would probably try doing this with jobs, specifically a job that implements IJobEntity. This would give each worker thread a subset of the total tiles, where each tile’s buffer is processed completely on the assigned worker thread:
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
// Your Components/DynamicBuffer element structs
public partial struct HexTile : IComponentData {
public bool ApplyModifier;
}
// Your DynamicBuffer<HexTileDataElement> will have 729 elements
public partial struct HexTileDataElement : IBufferElementData {
public float Value;
}
// The ISystem that processes each tile.
public partial struct ProcessHexTilesSystem : ISystem {
// This is an example field, you may have other things
// or nothing to pass into the job.
private float TestModifier;
[BurstCompile]
void OnCreate(ref SystemState state) {
state.RequireForUpdate<HexTile>();
state.RequireForUpdate<HexTileDataElement>();
TestModifier = 3f;
}
[BurstCompile]
void OnUpdate(ref SystemState state) {
// Create a new ProcessHexTileJob and schedule it in parallel.
// Set the state.Dependency back to the returned JobHandle.
state.Dependency = new ProcessHexTileJob {
Modifier = TestModifier
}.ScheduleParallel(state.Dependency);
}
// Implement a Job implementing IJobEntity that performs the processing
// for a single hex tile.
[BurstCompile]
partial struct ProcessHexTileJob : IJobEntity {
[ReadOnly] public float Modifier;
// Include or exclude required components as necessary in the Execute function definition.
// The important bit is to include 'ref DynamicBuffer<HexTileDataElement> tileDataBuffer'.
[BurstCompile]
public void Execute(in HexTile tileComponent, ref DynamicBuffer<HexTileDataElement> tileDataBuffer) {
// Loop through the DynamicBuffer's 729 elements
int numElements = tileDataBuffer.Length;
for (int i = 0; i < numElements; i++) {
// Get temp copy of the HexTileDataElement at index i
HexTileDataElement tileData = tileDataBuffer[i];
// Perform processing
HexTileDataElement transformedTileData = ProcessHexTileData(tileComponent, tileData);
// Set the value back into the buffer
tileDataBuffer[i] = transformedTileData;
}
}
[BurstCompile]
// Process the input tile data, returning the resulting tile data.
// Here, it just adds 1 or Modifier to HexTileDataElement.Value.
private HexTileDataElement ProcessHexTileData(HexTile tileComponent, HexTileDataElement tileData) {
// Whatever you do to each of the 729 elements of a tile.
tileData.Value = tileData.Value + 1*(tileComponent.ApplyModifier ? Modifier : 1);
return tileData;
}
}
}
I didn’t test this code, but it should be something to this effect.