0
\$\begingroup\$

I am new to Unity game dev and trying to expand my knowledge of data structs. I'm building a match-3 game, and I currently have a multi-dimensional ArrayList holding transform coordinates on a grid of x width and y height. I have game objects tied to these coordinates in world space, with the grid syncing the data back in game space. I am attempting to push these coordinates into the nested list (familyList) to be deleted pending 3 or more units being added to familyArrayList (seen below).

Here's the abridged code:

private static Transform[,] grid = new Transform[width, height];
public static ArrayList familyArrayList = new ArrayList();

// Go through game grid line by line and add game objects from game space into family ArrayList
for (int y = height - 1; y >= 0; y--)
        {
            for (int x = 0; x < width; x++)
            {
                if (grid[x, y] != null)
                {
                    // Add grid[x, y] to familyArrayList
                    familyArrayList.Add(grid[x, y]);
                    Debug.Log(familyArrayList[0]);

Output:

Green Unit(Clone) (UnityEngine.Transform)

How can I get familyArrayList to properly story the grid coordinates and not the game object the grid coordinates are referencing? i.e. familyArrayList[0] == '3,4' Should I instead use a nested list? At a later point in the code, I want to clear the game object from the board in world space as well as set the grid[x,y] to null:

// Loop through all family array and destroy game objects
foreach (var x in familyArrayList)
{
    Destroy(familyArrayList(x).gameObject); 
}
// Loop through all family array and set their values to null in grid as well
foreach (var x in familyArrayList)
{
    familyArrayList(x) = null;
}

But I get errors like "Argument 1: cannot convert from 'object' to 'int'" and "Non-invocable member 'Piece.familyArrayList' cannot be used like a method" which I can imagine are explained by my above problem of not storing the grid coordinates properly and instead storing the referenced game object. I'm truly stumped on this problem and thank anybody in advance who can point me in the right direction to solving this.

\$\endgroup\$
0
\$\begingroup\$

I think you might be confusing C# with Java or Javascript.

Change your Java list to a C# list and add the type so that the compiler know that we intend to store Transform objects in this list (unless you intentions is to mix it with other types, but that is not recommended anyways because you might run into casting errors):

public static List<Transform> familyArrayList = new List<Transform>();

Second possible mistake is, that your Debug.Log(familyArrayList[0]) is hard coded to the first element. I assume you intended to view the last added element:

Debug.Log(familyArrayList[familyArrayList.Count-1]);

C#'s foreach works different than Javascript. To to iterate through each GameObject, you need to do:

foreach (var x in familyArrayList)
{
    Destroy(x.gameObject);
}

And if you need to reference the list, you cannot use a foreach as that will only give you a reference to the element inside the list. So instead, just use a normal for-loop:

for (int i = 0; i < familyArrayList.Count; ++i)
{
    familyArrayList[i] = null;
}
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Firstly, as Jasper Citi mentioned in an earlier answer, you generally don't want to use the ArrayList type in C#. The generic List<T> type introduced later in the language's evolution covers the same use cases, with the benefit of strict typing for better efficiency.

How can I get familyArrayList to properly [store] the grid coordinates, and not the game object the grid coordinates are referencing?

Make a list of coordinates instead. We can use the Vector2Int type to store an (x, y) coordinate pair of integers.

public List<Vector2Int> coordinatesInFamily = new List<Vector2Int>();

You can then add coordinates to it like so:

for (int y = height - 1; y >= 0; y--) {
    for (int x = 0; x < width; x++) {
        // Skip empty grid cells.
        if (grid[x, y] == null)
            continue;

        // Add the coordinate pair [x, y] to our list.
        var coordinates = new Vector2Int(x, y);
        coordinatesInFamily.Add(coordinates);

        Debug.LogFormat("Added coordinates {0}, containing {1}", coordinates, grid[x,y].name); 
     }
}

Then you can clear your items like so:

foreach(Vector2Int coordinates in coordinatesInFamily) {
    // Destroy the game object at this position, and remove it from the grid.
    Destroy(grid[coordinates.x, coordinates.y].gameObject);
    grid[coordinates.x, coordinates.y] = null;
}
// Remove all entries from our family list in one fell swoop.
// (Faster and less error-prone than deleting them one at a time as we loop through)
coordinatesInFamily.Clear();

The reason you were getting errors before is due to some syntax mistakes:

  • When you type foreach (var x in familyArrayList), that x refers to an item in your collection, not the index of that item. (ie. here it's an Object, not an int) You can hover over the variable in your IDE to reveal what type it holds, or explicitly specify the type instead of var to make it more visible.

  • So you don't need to try to fetch the xth element from your list like this familyArrayList(x).gameObject. The variable x already holds the Transform itself - just boxed into a generic Object because ArrayList isn't strictly typed.

  • Also, even if you did need to index into the list, you used the wrong brackets for that. Those round parentheses () are used for function calls - use square brackets [] to index an item from a collection, like familyArrayList[0]

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.