0

I could ask a myriad of questions about arrays here, but I'll stick to one specific one. If you see other inefficiencies in the code below, please know that I am not trying to saddle you with the challenge of fixing that.

My specific issue is that I want to cycle through the whole length of my jagged menu[][] array, and as I go, extract a Vector3 value from my buttons[] array, and assign it to the Vector3[] array.

I am not sure why I can't do what I've posted below, but I get:

1) NullReferenceException error (on buttonPos[n] = buttons[n].transform.position,

2) "Field 'MatrixPicker.buttonPos' is never assigned to, and will always have its default value 'null'",

...when I try it. All my button[] GameObjects are located in the public fields where they belong in Unity.

Here is my code:

public class MatrixPicker : MonoBehaviour {

string[][] menu;
public GameObject[] buttons;
private Vector3[] buttonPos;

void Start () {

    menu = new string[][]{
        new string[]{"a"},
        new string[]{"b"},
        new string[]{"c", "d", "e"},
        new string[]{"f", "g", "h"}
    };


    int tot = 0;

    for (int i = 0; i < menu.Length; i++){
        string[] innerArray = menu[i];
        for (int a = 0; a < innerArray.Length; a++){
            tot++;
            int n = tot-1;
            buttonPos[n] = buttons[n].transform.position;
        }
    }
}
//other code
}

4 Answers 4

1

You need to initialize buttonPos before you try to set its elements. For example:

private Vector3[] buttonPos = new Vector3[menu.Length];  //Create an array that can contain one vector for each menu item

Once you have initialized the buttonPos array, you can use your loop to initialize each array element, which is a separate operation.

Sign up to request clarification or add additional context in comments.

2 Comments

I see, I can't set any elements before I initialize it. But I don't get the length I want from menu.Length because it is jagged.
You can use menu.SelectMany( x => x ).Count() to get total count.
1

As far as I can tell, you are not binding the GameObject, therefore it is allways pointing to nothing (null). You can try binding the Object with GameObject.FindWithTag? Also you need to initialize your arrays.

Example:

buttons = GameObject.FindGameObjectsWithTag("YOUR_OBJECT'S_TAG");

I can also recommend using foreach instead of a for loop:

for(Item item: list)
{
  //Your code;
}

Hope it helps!

3 Comments

public variables are visible in the editor, it is likely that OP has assigned the GameObject in the editor, the code won't reflect this and OP hasn't provided this info unfortunately, I believe he has though otherwise Unity would have fired a different error message.
Yes, that's right. Maybe initializing the array would help?
I'm sorry, I don't know if I used the proper terminology--I know I left out the word 'editor', but buried in my long question I did say I had all the button[] GameObjects located in their public fields in Unity. Foreach is probably a better idea, though, thanks!
1

buttonPos is a private variable, so I can infer that you are NOT initialising it before use. The below code will fix this error.

    void Start () {

        menu = new string[][]{
            new string[]{"a"},
            new string[]{"b"},
            new string[]{"c", "d", "e"},
            new string[]{"f", "g", "h"}
        };


        int tot = 0;
        int arrayLength = 0;
        foreach(string[] array in menu)
        {
            arrayLength += array.Length;
        }

        //initialise it here
        buttonPos = new Vector3[arrayLength];

        for (int i = 0; i < menu.Length; i++){
            string[] innerArray = menu[i];

            for (int a = 0; a < innerArray.Length; a++){
                tot++;
                int n = tot-1;

                //then you can assign it here
                buttonPos[n] = buttons[n].transform.position;
            }
        }
    }

you will also want to initially define it as null, to avoid a error from the compiler about use of a potentially undeclared variable

private Vector3[] buttonPos = null;

Alternative to Single Dimension buttonPos array using a list

Note how to turn it into a jagged array down the bottom matching menu

public class MatrixPicker : MonoBehaviour {

    string[][] menu;
    public GameObject[] buttons;
    private List<Vector3[]> buttonPos = new List<Vector3[]>();

    void Start () {

        menu = new string[][]{
            new string[]{"a"},
            new string[]{"b"},
            new string[]{"c", "d", "e"},
            new string[]{"f", "g", "h"}
        };


        int tot = 0;

        for (int i = 0; i < menu.Length; i++){
            string[] innerArray = menu[i];

            //initialise an array here to store this iteration of button positions
            bPosArray = new Vector3[innerArray.Length];

            for (int a = 0; a < innerArray.Length; a++){
                tot++;
                int n = tot-1;

                //set the current element as usual
                bPosArray[n] = buttons[n].transform.position;
            }

            //push back the new array into a list
            buttonPos.add(bPosArray);
        }
    }
    //other code




    void SomeOtherCode()
    {
        //if you need an array, just use
        Vector3[] anArrayOfTheButtonPosList = buttonPos.ToArray();

        //this will return a jagged array matching the menu array, with positions
    }
}

3 Comments

Your point about initialization is definitely the thing I was missing, thanks! However, unless I am missing something, menu.Length only gets me the number of columns/length of the first row/number of arrays in my jagged array. I have yet to figure out a more elegant way to get the total number of elements in a jagged array than the loop I found and used above.
edited with the most elegant solution I could think of. I honestly went searching for a while, for jagged arrays it seems there is nothing neater.
@SamHodak, also added an alternative to storing it in a single dimension array. Just add it to a list (much faster than resizing an array) and if you need, convert the list to a jagged array. This will retain the structure of the menu jagged array for the button positions also. - Also if the menu array never changes you could just use a known integer.
0

This works!

string[][] menu;
private int X = 0;
private int Y = 0;
public GameObject[] buttons;

void Start () {

    menu = new string[][]{
        new string[]{"a"},
        new string[]{"b"},
        new string[]{"c", "d", "e"},
        new string[]{"f", "g", "h"}
    };

    print("menu Length = "+menu.Length);


    int tot = 0;

    for (int i = 0; i < menu.Length; i++){
        string[] innerArray = menu[i];
        for (int a = 0; a < innerArray.Length; a++){
            tot++;
        }
    }

    int n = tot-1;

    Vector3[] buttonPos = new Vector3[n];

    int count = 0;
    foreach(Vector3 button in buttonPos){
        buttonPos[count] = buttons[count].transform.position;
        print(buttonPos[count]);
        count++;
    }
}

It is awful and ugly and hacky and I need to tidy it up and might be able to make it a lot more elegant with another foreach loop and maybe fewer variables--but it works! Thank you all! Everybody gets a car!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.