Reading and Writing in parallel from an ISystem

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.