Search Unity

Writing to native arrays inside systems

Discussion in 'Entity Component System' started by Imakhiil, Dec 9, 2018.

  1. Imakhiil

    Imakhiil

    Joined:
    Oct 11, 2013
    Posts:
    96
    Hi everyone! I've been trying to learn ECS and I ran into some issues. I have a NativeArray on the main thread that I need to populate with data from certain components. However, I don't know how to actually pass it to the system that is supposed to actually do the work.
    Afaik, it's impossible to set it directly. I was thinking about making it static but that on the other hand feels like a hack and not an actual solution. Or is this something that shouldn't be done in a system at all?

    This is the system in question:
    Code (CSharp):
    1.  
    2. [DisableAutoCreation]
    3. [BurstCompile]
    4. public class MapmodeSystem : JobComponentSystem
    5. {
    6.     [Inject] ComponentDataFromEntity<TileColor> tiles;
    7.     NativeArray<Color> colorsArray; /// <- I need to somehow set this from the main thread
    8.  
    9.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    10.     {
    11.         var job = new ApplyColorsJob()
    12.         {
    13.             tileColors = tiles,
    14.             colors = colorsArray
    15.         };
    16.         job.Run(this);
    17.  
    18.         return inputDeps;
    19.     }
    20.  
    21.     [BurstCompile]
    22.     struct ApplyColorsJob : IJobProcessComponentData<TiletteCoords, TiletteData>
    23.     {
    24.         [ReadOnly] public ComponentDataFromEntity<TileColor> tileColors;
    25.         [WriteOnly] public NativeArray<Color> colors;
    26.  
    27.         public void Execute(ref TiletteCoords coords, ref TiletteData data)
    28.         {
    29.             int s = 2 * 250 + 1;
    30.             int ws = 250;
    31.  
    32.             int f = coords.face;
    33.             int i = (ws + coords.x) + (ws + coords.y) * s;
    34.  
    35.             colors[i + i * f] = tileColors[data.data].color;
    36.         }
    37.     }
    38. }
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    The ECS way would be having data came out of ECS database not keeping data with the system. Then in your main thread you could create an entity with colors instead, the job executing next will find them.

    You could make an entity with dynamic buffer. Define IBufferElementData with one Color field then attach it as a buffer component.
     
  3. Imakhiil

    Imakhiil

    Joined:
    Oct 11, 2013
    Posts:
    96
    I see. Out of curiosity, is IBufferElementData something like an array "under the hood"? That NativeArray is up to 4 million elements long
     
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    In that case you should set capacity 1. It will get out of ecs database immediately and not taking up chunk space for other elements.
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    You may get some useful info here
    https://forum.unity.com/threads/nativearray-vs-dynamicbuffer-which-access-data-faster.584797/