Skip to content

Instantly share code, notes, and snippets.

@andrew-raphael-lukasik
Last active October 10, 2021 08:39
Show Gist options
  • Save andrew-raphael-lukasik/b1cba7b10407c7540e33f1c0a9930746 to your computer and use it in GitHub Desktop.
Save andrew-raphael-lukasik/b1cba7b10407c7540e33f1c0a9930746 to your computer and use it in GitHub Desktop.
tiny facade struct that provides [x,y] indexer accessors for arrays
// src* = https://gist.github.com/andrew-raphael-lukasik/b1cba7b10407c7540e33f1c0a9930746
using UnityEngine;
public struct Array2DView <T>
{
public T[] array;
public int width, height;
public T this [ int i ]
{
get
{
#if DEBUG
if( i<0 ) Debug.LogErrorFormat("index:{0} must be > 0",i);
if( i>=array.Length ) Debug.LogErrorFormat("index:{0} must be < {1} (array.Length)",i,array.Length);
#endif
return array[i];
}
set
{
#if DEBUG
if( i<0 ) Debug.LogErrorFormat("index:{0} must be > 0",i);
if( i>=array.Length ) Debug.LogErrorFormat("index:{0} must be < {1} (array.Length)",i,array.Length);
#endif
array[i] = value;
}
}
public T this [ int x , int y ]
{
get
{
#if DEBUG
if( x<0 ) Debug.LogErrorFormat("x:{0} must be > 0",x);
if( y<0 ) Debug.LogErrorFormat("y:{0} must be > 0",y);
if( x>=width ) Debug.LogErrorFormat("x:{0} must be < {1} (array width)",x,width);
if( y>=height ) Debug.LogErrorFormat("x:{0} must be < {1} (array height)",x,height);
#endif
return array[ y*width + x ];
}
set
{
#if DEBUG
if( x<0 ) Debug.LogErrorFormat("x:{0} must be > 0",x);
if( y<0 ) Debug.LogErrorFormat("y:{0} must be > 0",y);
if( x>=width ) Debug.LogErrorFormat("x:{0} must be < {1} (array width)",x,width);
if( y>=height ) Debug.LogErrorFormat("x:{0} must be < {1} (array height)",x,height);
#endif
array[ y*width + x ] = value;
}
}
public T this [ Vector2Int coord ]
{
get => this[ coord.x , coord.y ];
set => this[ coord.x , coord.y ] = value;
}
}
public static class ExtensionMethods_Array2DView
{
public static Array2DView<T> AsArray2D <T> ( this T[] array , int width , int height )
{
if( (width*height)!=array.Length ) Debug.LogErrorFormat("{0} (width) * {1} (height) != {2} (array.Length)",width,height,array.Length);
return new Array2DView<T>{ array=array , width=width , height=height };
}
public static Array2DView<T> AsArray2D <T> ( this T[] array , int width ) => array.AsArray2D( width , array.Length/width );
}
@Llama-W-2Ls
Copy link

Llama-W-2Ls commented Oct 10, 2021

Very nice. I usually implement my 2D arrays as 1D arrays and use some indexing math to convert Vector2 coords to their respective integer indexes.

You could extend this to 3D perhaps, using z * sizeY * sizeX + y * sizeX + x. This helped me a lot when I was doing a minecraft clone, which allowed me to store all blocks in the chunk in a single array, without needing an extra field in the block data to define its position in world space, since you can convert the integer index to a 3D coord by reversing the formula:

`int z = index / (sizeY * sizeX)

index -= z * sizeY * sizeX;
int y = index / sizeX

int x = index - y * sizeX`

Also, keeping data in a fixed 1D array has apparently faster lookup times than a multidimensional array or even a jagged array, and supposedly uses less memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment