Null ref when subscribing to event.

Not sure why I’m getting an error really. My other events are setup very similarly and they work correctly.

public class SomeClass : MonoBehaviour
{
    public delegate void SomeEvent();
    public SomeEvent someEvent;
}
private void OnEnable ()
{
    SomeClass.instance.someEvent += SomeMethod;
}

Should be working as expected right?

(Above code just typed quickly on phone, I know my singleton isn’t correct)

Is SomeClass.instance being assigned? And if so, is it being assigned before OnEnable is called? Put Debug.Log’s on both to see which order they’re being called in.

I would suggest you add some debugs to see what is null. Are you sure instance isn’t null for example?

haha… @StarManta had the same idea, but beat me to it.

Seems you are both correct. The instance is null just before the subscription to the event. Not sure why as it gets assigned in the Awake method, which I thought is called before OnEnable.

public class SomeClass : MonoBehaviour
{
    public static instance;

    private void Awake()
    {
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
       }
        instance = this;
    }
}

Am I missing something here? Using the debugger, the subscription code is reached before the instance is assigned. But I am baffled as to why.

One scripts onenable can be called before another scripts awake. I think the order is only gauranteed on a per script basis.

Note that for objects added to the scene, the Awake and OnEnable functions for all scripts
will be called before Start, Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.

Wow I was not aware of that. So how do people normally manage events in this way? Even the examples of event manager classes I’ve come across use a singleton design. So how can I assure I don’t keep getting this same problem?

EDIT: I could do a null check OnEnable, and then also subscribe in Start() but this seems a bit hackish… Or perhaps this is the norm?

You can force scripts’ execution order so that your singleton’s gets called first.

You can implement your singleton using an accessor; if it hasn’t been assigned yet, it uses FindObjectOfType to assign itself:

public class SomeClass : MonoBehaviour {
public static SomeClass instance {
get {
if (_instance == null) _instance = FindObjectOfType<SomeClass>();
return _instance;
}
}
private static SomeClass _instance;
1 Like

Thanks for the reply. Always tended to stay away from script execution order but I guess I need to use it in this case.

As for the second part of your reply; is there any real advantage of what you suggest over my above implementation of a singleton? I don’t see how finding the object by type is quicker/more advantageous of saying:
instance = this;

Or is it just to ensure references remain intact at run time when something tries to access the instance?

The advantage is that the situation that triggered this thread is impossible with a FindObjectOfType-based singleton. It doesn’t matter when you try to access the instance, it will always be able to find it.

Ahhh I see. Perfect. Thanks a bunch

I typically make my singletons assign their static instance variable in their constructor, which runs before all Unity magic methods.

However, this doesn’t let you do the normal detect-duplicates-and-destroy thing (for several reasons), so you have to ensure that you really only have one. I just have a one-line constructor saying instance = this.