How do i convert a 3dimensional array to be usable in a Job?

So i have a three dimensional array: Gridcell[,] (gridcell is a custom struct with some values)

and i need to use it in a Job, but Unity Jobs do not support normal arrays.
Is there another way than converting it into a one-dimensional NativeArray?

Multidimensional arrays in C# are all one dimensional under the hood. It’s just a matter of calculating the index. All you need are the sizes of each dimension. Lets say they are given like this:

int Dim0 = 10;
int Dim1 = 5;
int Dim2 = 6;

Of course there are different ways how you could “flatten” the index. Though just as an example lets say we want the last dimension (Dim2) to be the continuous dimension. That means two elements in this dimension are next to each other in memory. In this case you can calculate the flattened index like this given the 3 indices:

int index0, index1, index2;
int flattenedIndex = Dim1 * Dim2 * index0 + Dim2 * index1 + index2;

Of course we can extract Dim2 from the equation to get

int flattenedIndex =  Dim2 * (Dim1 * index0 + index1) + index2;

In this given example the element [2,3,5] would give you a flattened index of 60 + 18 + 5 == 83

Just think about it this way: The innermost array consists of 6 elements. The middle array consists of 5 innermost arrays. So those arrays are right next to each other. So index 0-5 are the indices [0,0,0] - [0,0,5]. The next 6 indices 6-11 represent [0,1,0] - [0,1,5]. And so on, so 12-17 represent [0,2,0] - [0,2,5]. The innermost and middle arrays combined have a size of 30 elements (Dim2 * Dim1 == 30). So every 30 indices we get into the next “outer most element”. So an index of 30 == [1,0,0] while an index of 60 == [2,0,0].

The built-in multidimensional array in C# simply does this for you behind the scenes. Though those multidimensional arrays are really slow because any access has to perform a range check for all indices and calculate the flattened index every time. That’s why using a single dimensional array and doing the flattening yourself can be much faster because you can precalculate the offsets when you operate in nested loops:

for(int i0 = 0; i0 < Dim0; i0++)
    int Dim0Offset = i0 *Dim1;
    for(int i1 = 0; i1 < Dim1; i1++)
        int offset = (Dim0Offset + i1) * Dim2;
        for(int i2 = 0; i2 < Dim2; i2++)
            int index = offset + i2;
            // array[index]

Of course when you just iterate through all indices you can simply carry the flattened index with you

for(int i0 = 0, index = 0; i0 < Dim0; i0++)
    for(int i1 = 0; i1 < Dim1; i1++)
        for(int i2 = 0; i2 < Dim2; i2++, index++)
            // array[index]

of if you don’t need the indices of each dimension you can of course use an ordinary loop:

for(int i = 0; i < array.Length; i++)
    // array

In a similar way you could also extract the dimension indices from the flattened index by simply reversing the calculations above. So for any given flattened index you can calculate the 3 dimension indices like this:
i0 = fIndex / (Dim1 * Dim2);
i1 = (fIndex % (Dim1 * Dim2)) / Dim2;
i2 = fIndex % Dim2;
Technically the first term would be
i0 = (fIndex % (Dim0 * Dim1 * Dim2)) / (Dim1 * Dim2);
Though the modulo is not required for the outermost index as long as the flattened index is inside the valid range. So for example a given index if 42 would result in i0==1, i1==2, i2==0