Unity Development – If it seems too hard, take a step back

Hear ye, hear ye! Here be a retelling of the trials and tribulations of following a tutorial with glossed over details. This one, to be specific:

An incredible tutorial

The challenge with tutorials is Goldilocks syndrome. It’s too easy, too hard, too long, too short, too detailed, or too simple. This tutorial was hitting some golden standard for me, it was easy to follow, it was short, it was detailed but not too much…. UNTIL I got stuck. And this is how I got unstuck.

I encountered the dreaded NullReferenceException error. The second issue with tutorials (and, dare I say, hubris) is thinking that the error is in itself an error. I Googled and read each post about this error, I slowed the video tutorial to half speed to stare at the code and listen for guidance, and checked and re-checked my code for null objects. And… nothing!

My saving grace was looking at what I was trying to achieve:

  1. Add object data (name, sprite image, etc) to my inventory
  2. Remove the object from the scene
  3. Add the object data to the inventory UI to show that the item was added to the user
  4. Live my life without the mounting frustration

Step 3 (and 4) were the bane of my existence.

1            InventoryItem item = InventorySystem.current.inventory[i];
2            GameObject obj = Instantiate(m_slotPrefab);
3            // Attach new prefab to Inventory Bar
4            obj.transform.SetParent(transform, false); 
5            // Get attached component of type ItemSlot (script)
6            ItemSlot slot = obj.GetComponent<ItemSlot>();
7            slot.Set(item, (i + 1).ToString()); <-- THIS LINE THREW THE ERROR

Line 1: Set the current item in the inventory array to the variable `item`
Line 2: Create a slot for the item to show up in the inventory bar
Line 4: Attach this slot to the Inventory Bar (this makes it so the bar grows as items are added and shrinks as they are removed)
Line 6: Reference the script `ItemSlot` that is attached to the m_slotPrefab object in the scene
Line 7: Set the values so the slot knows what image and other values to show

What I was trying to achieve (and eventually did)

For me, taking a step back from the madness of this block of code was my salvation. I knew that item, obj, and slot were all defined and present. So at that point I just thought I’d gone crazy and everything I had learned about Unity was a lie.

When I restarted building the UI by making predefined slots (vs making them dynamically with my prefab instantiation), I was able to successfully populate the items.

My simpler implementation with predefined (7) slots

Everything clicked when this implementation worked. I realized at that moment that I did everything right except the most simple step (which I imagine is why the tutorial didn’t even mention it)…. I did not link the prefab (slot object) to its own children.

The NullReference was not in the slot at all, it was in the values it was trying to set:

public class ItemSlot : MonoBehaviour
{
    [SerializeField]
    public Image m_icon;          <-- lol forgot
    
    [SerializeField]
    public TextMeshProUGUI m_label;  <--- yup, this too
    
    [SerializeField]
    public TextMeshProUGUI m_keyLabel; <--- this one, also

    public void Set(InventoryItem item, string key) {
        m_icon.sprite = item.data.icon;
        m_label.text = item.data.displayName;
        m_keyLabel.text = key;
    }  
}

And this is where I should have set the relationship:

On the left is the ItemSlotPrefab (or m_slotPrefab in the code) and its hierarchy. On the right are its properties and under ItemSlot I had previously not dragged in the reference to each of the children on the left. So really, the script was targeting NOTHING when trying to set the values. NULLREFERENCE.

Anyway, after I came back to life after seeing the error of my ways I had a functional inventory that functions as shows in the tutorial.

  1. We define inventory items in our scene that have a script attached (fig 1)
    • ItemObject which gives the item an onHandlePickup function (this adds the item to the inventory and destroys the object from the scene)
      • This also adds a reference to the inventory item data which is predefined as an asset and attached
  2. We generate a slot using the m_prefabSlot and attach it so the inventory bar is dynamically sized (fig 2)
  3. We create and instantiate a singleton public Inventory object so it can be accessed from pretty much anywhere in the code
  4. Enable checking inventory for items and “re-adding” them to the scene if necessary (fig 2)

References:

fig 1:

Inventory Item Data added to ItemObject script
See Inventory Item Data referenced under ItemObject script
Script using the item data

fig 2:

Checking if the statue is in the inventory. Placing an instance of the prefab back to the scene. Deleting it from inventory.
In the altar script we pass where to place the objects and a reference to the object we can make appear.

The end! Thank you for getting to the end of this emotional saga! ūüôā

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s