Hi!
I want to make a game where you can place buildings in a grid. And I want to save the state of every cell in the grid, in an array.
I tried doing that like this:
private GameObject[][] Grid;
// Initialization
void Start ()
{
Grid = new GameObject[41][];
for (int i = 0; i < 41; i++)
{
Grid[i] = new GameObject[41];
for (int j = 0; j < 41; j++)
{
Grid[i][j] = null;
}
}
And when you place a building, this happens in the code:
if (Grid[gridx+20][gridz+20] = null)
{
plottedbuilding = Instantiate (building);
plottedbuilding.transform.position = new Vector3 (gridx,0,gridz);
Grid[gridx+20][gridz+20] = plottedbuilding;
}
else
{
Debug.Log ("There's already a building here")
}
But somehow this setup doesn’t work, and I always get the message “There’s already a building here”.
What am I doing wrong?
Thanks in advance!
In C#, there is a difference between jagged arrays
object[][] myArray;
and multi-dimensional arrays
object[,] myArray;
You declare a jagged array, its elements are supposed to be arrays, in your case arrays of GameObjects.
In the second code snippet, you then you try to access it as if it was a multi-dimensional array.
You may want to use a two-dimensional array, not a jagged one.
But the problem is that I later want to expand the array, and I was told that that’s not possible with multi-dimensional arrays.
I’m only a beginner in Unity so I’m sorry if I’m making obvious mistakes.
Is there no way to use a jagged array in my situation, or would it really be preferable to use 2d arrays?
Edit: And can you tell me where in the code I try to access it as a 2D array?
You cannot expand any array unless you create a new one with a bigger size and copy everything to the new one.
That could be done with a wrapper class, but there are already classes that provide good implementations.
Have a look at collections like ArrayList, List etc.
I looked up List, and it might indeed be better for my needs. But I still don’t understand exactly how I can practically use it in my case.
Would you be able to help me further? I don’t understand how to use it in regard to GameObjects specifically. Like I said, I’m only a newcomer in C# so all help would be welcome!
Edit: I made it work! So there’s no need for explanation anymore
There are a few questions to answer and approaches to think about before you start to implement such things, just a few of them being:
Is there really a need to expand it dynamically?
The point is, as i thought about it, it doesn’t make much sense to use some kind of collection either, as you will always need the current max size to add an object to a specific index. So you may stick to arrays, but i do not recommend jagged arrays.
If you want to restrict the area to a part of the max. size, is it enough to start out with the max. possible size and restrict the placement with logic rather than resizing the array when time has come?
This is another way to solve the issue and allows for an easy use of x-Dimensional arrays.
Do you actually need the grid setup? Let’s do some brainstorming for a complex building system, because there’s a point you might want to switch to an alternative:
Imagine you have a building that does not only take one cell, but 4 (2x2). That’s still easy to figure out as well, isn’t it - just set the neighbor cells to be in use as well.
Next, allow non-square shapes, such as 2x4 cells. Same as above, but what about different orientations (in steps of 90 degrees)?
Still okay to figure that out.
But what about L or U shapes with said rotations? It’s already getting harder …
Or let’s just allow every possible orientation - your grid is probably not the way to go anymore.
That’s the point where i dropped the grid-concept for my current project and I’ll probably use another approach which is based on the physics system. That does allow free placement all over the place, can be restricted to a virtually existing grid of any precision and allows every rotation, too.
I don’t exactly understand what you mean.
When I think about it, using a List makes sense. I use the List to see if certain cells are free or taken and I will use it later for path finding. The player will be able to rotate buildings (no matter what shape) per 90° before placing them, but in the end it wouldn’t be that difficult to set the appropriate neighbor cells as taken when a building gets placed.
In the end, arrays and lists just seem like the same things but with different executions. And I just want to store some information about the city, to get some kind of image about it. And I think that’s both possible with arrays and lists. And I now chose for the use of a list. Could you explain more of what you mean in your previous reply?
They are similar but not the same. Most of it has to do with the footprint they have. The biggest plus is that a List is non-contiguous, it can grow in size without re-allocating memory for the entire collection.
A simple rule of thumb is:
Is the collection static (a.k.a. a fixed size)? Use Array.
Can the collection be dynamically changed (adding or deleting items from the collection)? Use Lists.
Avoid ArrayList, it is basically just an Array with slower performance and less functionality then a List, and was mostly meant for Legacy code that didn’t support the IList interface.
I think that’s not quite correct.
C#'s List is backed by an array and also uses the indexer. The “real” non-contiguous List is LinkedList.
Well, we’re talking about grids and you want to add something at a specific index, thus you will need to allocate everything from the beginning anyway.
Collections usually start with a size of 0, so you cannot assign e.g. the 20th element without adding 19 others. You can expand it without copying everything on your own, but that’s just a lil advantage. Sorry for the confusion.
It is due to the way List handles memory allocation. Instead of allocating precisely the amount of memory it needs like an array does, it allocates double as much and keeps doing that whenever needed (it doubles the size of it’s internal array). That means that it does not need to reallocate memory and copy over the array every time you add an item to the List making it “non-contiguous”.
Here is the sneaky little method of the List class that ensures the capacity of the array:
private void EnsureCapacity(int min) {
if (_items.Length < min) {
int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
if (newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
I know, I’ve already had to implement something similar for learning purposes long time ago (C++ though), but I was rather referring to the internal structur, the items are still contiguous (in memory), or am i misunderstanding the meaning of “contiguous” in this context?
In contrast to that, the items in the LinkedList just reference their “neighbour-elements”, so they can be (simply said) placed anywhere in memory, hence no re-alloc.
I think that in this context it means that the memory allocation is not contiguous with the total memory footprint of the array, however I am not sure, never researched why they call it a non-contiguous collection but that seems the most likely reason for me.