Misalignment of 2D Array - Data structure

Hello everyone,

See the attached picture. I wrote a code, that each entry in a 2D-Array has an ID.
For a reason that I cannot explain, the first element [0,0] of the array gets the last ID → 99.

I expected, that the element [0,0] gets the SquareID = 0. But it doesn’t. Instead it has the highest possible value in the zero-based counting → 99 for the 10 by 10 array size.

Can anyone help? :frowning:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CodeSnippets : MonoBehaviour
{

    private int gridSize = 10;
    private Vector3 offSetVector = new Vector3(0, 0, 0);
    private Vector3 basicSquareLocation = new Vector3(0, 0, 0);

    private bool[,] cellInfo;
    private int squareID = 0;

    public GameObject basicSquare;

    private void Awake()
    {
        cellInfo = new bool[gridSize, gridSize];
    }

    private void Start()
    {
        CreateGrid();
    }

    private void CreateGrid()
    {
        for (int column = 0; column < gridSize; column++)
        {
            for (int row = 0; row < gridSize; row++)
            {
                // Set bool in array at position [column, row]
                cellInfo[column, row] = SetTrueByProbability(0.75f);

                // Calculate Offset Position from one square to next one. 
                // Starting in the left lower corner. Going up row by row.
                // Continue from column to column until the right upper corner.
                offSetVector = new Vector3(0.5f * column, 0.5f * row, 0);
                basicSquareLocation = transform.position + offSetVector;

                // Instantiate the basicSquare Prefab | SquareProperty
                // Compoment is already attached to Prefab.
                Instantiate(basicSquare, basicSquareLocation, transform.rotation);

                // Set SquareProperty for each Square[column,row].
                basicSquare.GetComponent<SquareProperty>().SetSquareRowID(row);
                basicSquare.GetComponent<SquareProperty>().SetSquareColumnID(column);
                basicSquare.GetComponent<SquareProperty>().SetSquareID(squareID);

                // Add +1 to SquareID.
                squareID++;
            }
        }
    }

    private bool SetTrueByProbability(float probability)
    {
        float randomValue;

        randomValue = Random.Range(0, 1f);

        if (randomValue <= probability)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

Instantiate creates and returns an Object, it doesnt override it…

so if you want to create a new object and then change its properties, you want to read out the object you created first, like:

GameObject newSquare = Instantiate(basicSquare, basicSquareLocation, transform.rotation);
// Set SquareProperty for each Square[column,row].
newSquare.GetComponent<SquareProperty>().SetSquareRowID(row);
newSquare.GetComponent<SquareProperty>().SetSquareColumnID(column);
newSquare.GetComponent<SquareProperty>().SetSquareID(squareID);

otherwise you are just overwriting the id of the same initial square in basicSquare

Edit: just to make it clearer, your problem lies in line 44. you never read out your newly created object, you only change the properties of the first one, thus every step of the loop including the last one overwrites the ID of your first object

1 Like

use debug.log to find out what is happening

Just as addition to my previous answer, a neat trick to make your code simpler and more performant:

if you do Instantiate on a Monobehaviour (like your SquareProperty), it will automaticly do the Instantiate on the GameObject that component is attached to, while returning the component of the newly created object…

in other words, these 2 code snippets do exactly the same thing:

  1. with GameObject like it is right now:
//[...]

public class CodeSnippets : MonoBehaviour
{
    //[...]
    public GameObject basicSquare;
    //[...]
    private void CreateGrid()
    {
                //[...]
                // Instantiate the basicSquare Prefab | SquareProperty
                // Compoment is already attached to Prefab.
                GameObject newSquare = Instantiate(basicSquare, basicSquareLocation, transform.rotation);
                // Set SquareProperty for each Square[column,row].
                newSquare.GetComponent<SquareProperty>().SetSquareRowID(row);
                newSquare.GetComponent<SquareProperty>().SetSquareColumnID(column);
                newSquare.GetComponent<SquareProperty>().SetSquareID(squareID);
                //[...]
    }

    //[...]

}
  1. changed basicSquare from GameObject to SquareProperty, no longer needing the GetComponent:
//[...]

public class CodeSnippets : MonoBehaviour
{
    //[...]
    public SquareProperty basicSquare;
    //[...]
    private void CreateGrid()
    {
                //[...]
                // Instantiate the basicSquare Prefab | SquareProperty
                // Compoment is already attached to Prefab.
                SquareProperty newSquare= Instantiate(basicSquare, basicSquareLocation, transform.rotation);
                // Set SquareProperty for each Square[column,row].
                newSquare.SetSquareRowID(row);
                newSquare.SetSquareColumnID(column);
                newSquare.SetSquareID(squareID);
                //[...]
    }

    //[...]

}
1 Like

I love you!
Your explanation was fantastic! Now it works and I see clearer.
Next I will try to implement the more elegant version you’ve proposed in your second reply!