Callback returning null, why???

Unity is saying that ActorEquipment.actorEquipmentInstance.onEquipmentChanged += OnEquipmentChanged; is null and thats it. No other information. (Thanks Unity, thats helpful…) Visual Studio is happy with the script/s.

Yes, I stole the script from a tutorial and tweaked it for my purposes.
I know its something to do with the Callback method thing…what every that is…(Still cant get my head around it, I have a poor IQ, therefore im not able to grasp concepts easily)

After going through it repeatedly, I cant find any reason why it would return null, despite I have no idea what im typing.

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

public class BaseAnimatorController : MonoBehaviour {

    void Awake()
    {
        ActorEquipment.actorEquipmentInstance.onEquipmentChanged += OnEquipmentChanged;
    }
      
    void OnEquipmentChanged(Equipment newItem, Equipment oldItem)
    {

    }
}

//---------------------------------------------------------------------------

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

public class ActorEquipment : MonoBehaviour {

public static ActorEquipment actorEquipmentInstance;

    void Awake()
    {
        actorEquipmentInstance = this;
    }

    public delegate void OnEquipmentChanged(Equipment newItem, Equipment oldItem);
    public OnEquipmentChanged onEquipmentChanged;
  
     public void Equip(Equipment newItem)
    {
        int slotIndex = (int)newItem.EquipmentType;

        Equipment oldItem = Unequip(slotIndex);

        if (onEquipmentChanged != null)
        {
            onEquipmentChanged.Invoke(newItem, oldItem);
        }

        currentEquipment[slotIndex] = newItem;
    }

    public Equipment Unequip(int slotIndex)
    {
        Equipment oldItem = null;
        if (currentEquipment[slotIndex] != null)
        {
            oldItem = currentEquipment[slotIndex];
            inventory.AddToInventory(oldItem);

            currentEquipment[slotIndex] = null;

            if (onEquipmentChanged != null)
            {
                onEquipmentChanged.Invoke(null, oldItem);
            }
        }
        return oldItem;
    }
}

A null reference means that you’re trying to dig into something that’s null, which almost always means that something to the left of a dot is null. In this case, ActorEquipment is a class, so that’s not what’s null, so that leaves actorEquipmentInstance.

When is actorEquipmentInstance null? Before its Awake() runs. Here is where it’s important to know that execution order of the same function between different scripts isn’t guaranteed - all the Awake()'s will run before all the start()'s, but there’s no guarantee which Awake() will run first.

So what’s almost certainly happening is that BaseAnimatorColler.Awake is running before ActorEquipment.Awake(). If you change BAC’s Awake to Start, it will be guaranteed to run after AE’s Awake, and actorEquipmentInstance will have its value set.

In general: any initialization that stands on its own should be done in Awake, while anything that depends on other objects should be done in Start. That way you’ll generally avoid trying to access variables on other objects that haven’t been set yet.

(This also assumes that there’s an ActorEquipment in the scene)

4 Likes

THAT Sir! Is a 5 star answer! Explained PERFECTLY! Gotta be honest, these are the answers I prefer!

1 Like