Last active
October 10, 2021 08:39
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.