0

Since we cannot serialize multi-dimensional arrays (in Unity) we are limited to using one dimensional arrays along with math to convert from x,y pairs to an index and back out. Here are the current conversion algorithms:

int Width = 3; // Number of cells along the x axis
int Height = 3; // Number of cells along the y axis

GameObject[] Cells = new GameObject[ Width * Height ]; 

public int CalculateIndex( int x, int y )
{
    return y * Width + x;
}

public void CalculateXY(int i, out x, out y)
{
    x = i % Width;
    y = i / Width;
}

Now, I have the problem where I need to create a 3 dimensional grid which introduces Depth as well as the z axis but I can't figure out how to inject the changes into the methods above... I'm having a mental block.

I found this post that explains some of it:

How to "flatten" or "index" 3D-array in 1D array?

However, my array is not in the HEIGHT, WIDTH, DEPTH (y,x,z) order but rather the WIDTH, HEIGHT, DEPTH (x,y,z) order. Furthermore I need the algorithm to turn it from an index back into x,y,z values.

Thanks, - jeff

Community
  • 1
  • 1
Jeffrey
  • 21
  • 2
  • 1
    `x + Width * (y + Height * z)`, `x = i % Width; y = (i /= Width) % Height; z = i / Height`. – user4003407 Feb 19 '17 at 01:53
  • So jagged arrays are not an option? – Slai Feb 19 '17 at 01:57
  • 1
    Maybe this one question could be helpful to you: http://stackoverflow.com/questions/3613429/algorithm-to-convert-a-multi-dimensional-array-to-a-one-dimensional-array . I find its best to circumvent these kind of mental blocks by visualising the problem. – pijemcolu Feb 19 '17 at 08:33
  • using modulus and division is very inefficient in implementation: division takes a number of cycles. Are you building a game? It might be more efficient to use a (jagged-)jagged array for all your own operations and then convert it to a single array for serialization. – JHBonarius Feb 19 '17 at 08:48

1 Answers1

0

Edit: please check the link shared by pijemcolu, good explanation is there.

~~

I'm using JS code so that you / others can directly test it below.

The main functions that you are looking for are:

function CalculateIndex(x, y, z)
{
    return (x * HEIGHT * DEPTH) + (y * DEPTH) + z;
}

function CalculateXYZ(i)
{
  var ret = {};
  ret.x = Math.floor(i / (DEPTH * HEIGHT));
  ret.y = Math.floor(i / DEPTH) % HEIGHT;
  ret.z = i % DEPTH;

  return ret;
}

Note: you won't need to use floor as you are using int datatype in C#.

$(function(){
  $('#process').click(function(){
    var WIDTH = +$('#w').val();
    var HEIGHT = +$('#h').val();
    var DEPTH = +$('#d').val();
    
    var _x = +$('#X').val();
    var _y = +$('#Y').val();
    var _z = +$('#Z').val();
    
    if(_x >= WIDTH || _y >= HEIGHT || _z >= DEPTH)
    {
      $('#output').text('Invalid input');
      return;
    }
    
    function CalculateIndex(x, y, z)
    {
        return (x * HEIGHT * DEPTH) + (y * DEPTH) + z;
    }

    function CalculateXYZ(i)
    {
      var ret = {};
      ret.x = Math.floor(i / (DEPTH * HEIGHT));
      ret.y = Math.floor(i / DEPTH) % HEIGHT;
      ret.z = i % DEPTH;
      
      return ret;
    }
    
    var ind = CalculateIndex(_x, _y, _z);
    var retXYZ = CalculateXYZ(ind);
    
    $('#output').html('Calculated index is: ' + ind + '<br/>' + 'Calulated X Y Z are: ' + JSON.stringify(retXYZ));
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Width: <input id='w' type='number' value='4' min=0></p>
<p>Height: <input id='h' type='number' value='3' min=0></p>
<p>Depth: <input id='d' type='number' value='2' min=0></p>
<hr>
<p>x: <input id='X' type='number' value='0' min=0></p>
<p>y: <input id='Y' type='number' value='0' min=0></p>
<p>z: <input id='Z' type='number' value='0' min=0></p>
<p><button id='process'>Process X Y Z</button></p>
<div id='output'></div>
Vivek Athalye
  • 2,974
  • 2
  • 23
  • 32