Hey all,
I’ve been trying to create a 2D world generator for the past couple of days now. It’s actually coming along great! However, I’ve been comparing my code to others, and I’ve seen a lot of people using float [ , ]. What does this mean?
You could look into multidimensional arrays. You can declare it like this or use an array of arrays.
It allows you to address the array contents with two indexes, typically x and y:
var content = map[101, 13]
However, this is only minimally more convenient than a linear array where you can simply calculate the index using the simple formula:
var index = (y * width) + x;
var content = map[index];
Typically one would wrap this in its own simple class so you could still do the above but without the use of a multidimensional array. Creating custom collection classes is best practice on top because it allows you to swap out the implementation details (ie arrays => list => native collection) at any time without affecting other code.
Linear arrays have a huge performance benefit when iterating as the memory layout is continuous, leading to more cache hits whereas a “jagged” array or array of arrays (or lists for that matter) may get spread throughout memory.
But for generating coordinates, why wouldn’t you just use a nested for-loop of x and y, and just create a Vector2 position?
I could be wrong, but I believe this is for looking up coords. If you want to find coord 495, 322 from a list of vectors, you would need to look for all of them. If they are in a 2D array you can simply get the node at that coord
How would you do that? Would you put each array in a list? But how would you be able to find that specific one?
If you need to get a reference at a random coordinate where not every coordinate has a reference (or value or whatever) then a Dictionary would be more efficient.
If you know that your coordinates are never greater than 65,535 then you could use a uint as key:
Dictionary<uint, TheValue>
Then bitshift y coord onto x:
uint key = (uint)x + (uint)y << 16;
Not sure if casting is necessary.
If the map has a fixed width see above:
var key = (y * width) + x;
Right and if the coordinates are larger, you could use a long
Though using a struct like a Vector2Int as key would also work.
One, what is a uint?
Two, hoq does this relate to multidimensional arrays?
Three, why would you bitshift?
These are all just advanced “what we used to do oldskool” to combine X/Y coords into a single indexable scalar. Back in the day if you wanted more than one dimensions, YOU did the address / indexing computations yourself.
It’s 2024… you don’t need that.
Just use a Vector2Int and put your stuff in a Dictionary<Vector2Int,Thingy>, where Thingy is whatever you want to track at each cell… could be a GameObject or your own concept of some cell structure.
If you want an example of manipulating things in a 2D grid, here’s my Match3 game:
Full source linked below it.
Yeah, your method seems more in line with what I would think people would do. I’m personally using unity’s grid system. So I guess my question would be: why do people use a custom grid class instead of the grid system? Also the Vector2Int dictionary seems a lot better than a multidimensional array (though I still have no idea what those are used for in world gen))
To not be tied to Unity, or just because they want some function that it doesn’t provide.
Grid systems like this are some of the lowest most boring-est data structures… yes it is important to select the correct one and use it properly, but it is MORE important that you wrap it in your own package and API, you can swap out the underlying storage mechanism anytime you outgrow it.
It’s infinitely flexible as it maps a 2-dimensional coordinate space arbitrarily, but more complex and less performant.
Look up sparse arrays / sparse matrix: let’s say there’s umpteen billion possible places you can be in the world and no way you could ever allocate a 2D array using [,] and have it fit in any reasonable amount of memory. Sparse arrays let that happen, as most of the 2D numeric space is empty.
Ok, so how would you find a coordinate using a multidimensional array? From what I can tell, it’s not like a dictionary where you can just search for a certain key value?
Using a Dictionary is great if you only need a subset of the locations on the grid as it only stores those locations but if you need most of the locations and need to scan through it rather than perform lookup on specific elements it’s also the least performant and memory efficient as you’re not only storing the key but have overhead from using it.
The main advantage to T[,] is that the data is stored contiguously in memory meaning it has very high cache and memory bandwidth efficiency making it ideal for data-oriented design.
Yes, but let’s say I do this:
Grid [ , ] grid;
And then,
grid = new Grid [x,y];
How would I access this later?
These data structures aren’t for “finding.” They are for retrieving, also called “dereferencing.”
The idea is you have a coordinate in mind and you say “What is here?”
With a grid, if grid[x,y] is where you are, then grid[x+1,y] is the one immediately to the right (east).
You access them the same way you would access a 1D array just with one more number.
Grid[,] grid = new Grid[x,y];
Grid element = grid[x,y];
grid[x,y] = element;
That makes sense thank you! But how would we know our grid’s position? Would we use getLength(0) and gethLength(1) and put it in a vector 2?
If you have an array that is sized equal to the grid the position is the X and Y dimensions of the array.
var position = new Vector2Int(5, 5);
var element = grid[position.x, position.y];
Just quick note: Dictionary lookup is supposedly faster if you use int (or long) as keys, hence avoiding struct types as key can make sense if performance is really precious.