Search Unity

2D native collections

Discussion in 'Entity Component System' started by JakHussain, Jul 4, 2019.

  1. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    I can't seem to figure out the best way to do this. I've got a jagged array of shorts of which I need to calculate the highest value, the index of the highest value and the sum of the values for each row. (In this example I'm just overwriting the result of the previous row for simplicity's sake).

    Code (CSharp):
    1. private void MultiThread ()
    2.     {
    3.         PeaksCalculator calc = new PeaksCalculator ();
    4.  
    5.         calc.radiation = new NativeArray<NativeArray<short>> (radiation.Length, Allocator.TempJob);
    6.         calc.results = new NativeArray<int> (3, Allocator.TempJob);
    7.  
    8.         for (int i = 0; i < radiation.Length; i++)
    9.         {
    10.             calc.radiation[i] = new NativeArray<short> (radiation[i], Allocator.TempJob);
    11.         }
    12.  
    13.         JobHandle handle = calc.Schedule (calc.radiation.Length, calc.radiation.Length / 4);
    14.  
    15.         handle.Complete ();
    16.  
    17.         peak = calc.results[0];
    18.         peakIndex = calc.results[1];
    19.         cummulative = calc.results[2];
    20.  
    21.         calc.radiation.Dispose ();
    22.         calc.results.Dispose ();
    23.     }
    Code (CSharp):
    1. [BurstCompile]
    2. public struct PeaksCalculator : IJobParallelFor
    3. {
    4.     [ReadOnly] public NativeArray<NativeArray<short>> radiation;
    5.  
    6.     public NativeArray<int> results;
    7.  
    8.     public void Execute (int index)
    9.     {
    10.         for (int j = 0; j < radiation[index].Length; j++)
    11.         {
    12.             if (radiation[index][j] > results[0])
    13.             {
    14.                 results[0] = radiation[index][j];
    15.                 results[1] = index;
    16.             }
    17.  
    18.             results[2] += radiation[index][j];
    19.         }
    20.  
    21.         results[2] /= 1000;
    22.     }
    23. }
    I get an error saying I'm basically not allowed to make a native array of native arrays but when I try making a single job for each row, when compared to just running the same logic on update, the performance on the main thread goes up but the overall framerate goes down for some reason.

    Any ideas on where I'm going wrong?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    You can't use native container inside native container. Just falt 2D array to 1D, or use NativeMultiHashMap.
     
    MNNoxMortem and Krajca like this.
  3. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    481
    Code (CSharp):
    1. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    2. public static void Set2D<T>(this NativeArray<T> array, int x, int y, T value, int width) where T : unmanaged
    3. {
    4.     int flatIndex = FlattenIndex(x, y, width);
    5.     if (flatIndex < 0 || flatIndex >= array.Length)
    6.         throw new IndexOutOfRangeException($"Index {flatIndex} is out of range {array.Length}. [{x},{y}], width:{width}");
    7.     array[flatIndex] = value;
    8. }
    9.  
    10. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    11. public static T Get2D<T>(this NativeArray<T> array, int x, int y, int width) where T : unmanaged
    12. {
    13.     int flatIndex = FlattenIndex(x, y, width);
    14.     if (flatIndex < 0 || flatIndex >= array.Length)
    15.         throw new IndexOutOfRangeException($"Index {flatIndex} is out of range {array.Length}. ({x},{y}), width:{width}");
    16.     return array[flatIndex];
    17. }
    18.  
    19. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    20. public static int FlattenIndex(int x, int y, int width) => y * width + x;