1
\$\begingroup\$

I'm trying to create a hotbar system where you can press 1 through 0 to activate abilities placed in the hotbar slots. Instead of a giant block of if/else statements I want to make a single check that can match the GameObjects in the array "Slots" with an associated KeyCode. To do that I made a simple for loop that adds a pair.

When I try to run the following code, I get the error NullReferenceException: Object reference not set to an instance of an object. I would assume this means that the object Slots[i] doesn't exist, but it definitely does for every iteration of the loop; I made 10 empty "slot" objects that are children of the Hotbar Object that runs this script.

Here's the code:

[SerializeField]GameObject[] Slots;
Dictionary<GameObject, KeyCode> SlotKey;

void Start()
{
    for (int i = 0; i < 10; ++i)
    {
        print(Slots[i].name);
        SlotKey.Add(Slots[i], (KeyCode)i + 48);
    }
}

When this code runs, it prints only the name of the first object in Slots (slot 0) and then gives me the error message. Running this loop with only the print works correctly, printing the names of slots 0 through 9. I also tried a foreach version:

    int i = 0;
    foreach (GameObject s in Slots)
    {     
        print(s.name + (KeyCode)(i + 48));
        SlotKey.Add(s, (KeyCode)(i + 48));
        
        i++;
    }

This resulted in the exact same issue where every part of this loop works correctly except for SlotKey.Add.

Why does my dictionary seem unable to find the gameobjects in my array when the for loop itself seems to have no trouble with it?

\$\endgroup\$
3
  • \$\begingroup\$ I'd suspect that you've modified the code in your question versus the code you tested. The symptoms you describe for the second example would make sense if your print line occurred before the SlotKey.Add() line, rather than after, as you've shown here. Unless the error message is different than the one you've quoted. \$\endgroup\$
    – DMGregory
    Jun 16 at 14:53
  • \$\begingroup\$ Right sorry, print does print once but only if it's before SlotKey.Add(). Editted. \$\endgroup\$ Jun 16 at 15:15
  • \$\begingroup\$ It's important to ensure the code you post here is line-for-line the code you test, to avoid getting correct answers about the wrong question. ;) You should also get in the habit of experimenting with the code first to eliminate irrelevant elements. For instance, does the problem have anything whatsoever to do with "using a for loop"? Delete the for loop and try assigning a single dictionary element to test it. That would show you the for loop is unrelated, and maybe even help you spot your error yourself before taking the time to post a question at all. \$\endgroup\$
    – DMGregory
    Jun 16 at 15:28

1 Answer 1

2
\$\begingroup\$

You forgot to assign a value to your dictionary.

Dictionary<GameObject, KeyCode> SlotKey = new Dictionary<GameObject, KeyCode>();

Until you assign a value to a reference type variable, it holds the value null. Attempting to use any member of a null reference, such as calling SlotKey.Add(), will throw a null reference exception, because there's no dictionary there to call the function on, just an empty space for one.

You might have fallen out of the habit of doing this for value type fields, which have a non-null default assigned automatically, and serialized fields, which the serializer assigns for you based on the values in the inspector. But the serializer won't touch dictionaries, so that's up to you to initialize.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .