Singleton firing an Action event

Hello everyone,

I’m developing a turn-based game where I use a Singleton for my Turn System (it seemed logical).
Now when this TurnManager starts a new turn, it fires an event so that everything that needs to do something specific at turn start can be aware it’s a new turn and do their things.

So in my TurnManager I have :

public event Action OnStartTurn;

private void Awake() {
if (Instance != null && Instance != this) {
Destroy(this);
} else {
Instance = this;
}
}

public void NewTurn() {
OnStartTurn.Invoke();
}

And on an GameObject Unit I want to subscribe :

private void OnEnable() {
TurnManager.Instance.OnStartTurn += DoStuff;
}

My problem here is that on execution, it does a nullreference exception because the OnEnable of Unit is called before the Awake of TurnManager.

The simple fix is to subscribe to the event in the Start function of Unit instead of OnEnable. But I’m not sure if it feels right or if I’m on a wrong path allover.
I’ve always seen and used OnEnable and OnDisable to subscribe / unsubscribe to events. But I’m quite new to using Singletons and it’s the 1st time I’m firing an event from a Singleton.
I’ve searched the web but events and singleton are always opposed as design patterns. Though here, I feel like it makes sense that my TurnManager is a Singleton, and I think it makes sense too to alert everyone that a new turn has started through an event. Am I missing something here why Singleton and Events shouls not be used together ? Or is it something normal, as is to use Start instead of OnEnable to susbscribe to that event.

Thanks in advance to anyone who will share their insights with me or point the flaws and stupidities of my approach. I’m here to learn.

No its pretty normal. Self initialisation in Awake/OnEnable. Anything that requires something else to be initialised goes in Start.

Though ideally your monobehaviour singletons don’t start already in a scene. Make them lazily-load themselves, either by simply constructing themselves if they don’t need to reference any assets, or load themselves out of Resources/Addressables if they do need to be authored first. Thus there’s no issues with race conditions.

Thank you for your answer.
What is the advantage of lazy loading for my singleton when I know I’ll need it for my scene ?

Like I already said, to prevent race conditions. The first time it gets accessed it should fully initialise.

And it’s general good practice to never have your singletons in a scene. If they are, why are they a singleton then? Why can’t they just be treated like a normal monobehaviour and referenced directly?

Hi, a little follow-up here.
So I ended using a self constructing lazy load for my TurnManager and it works perfectly.

I used the Singleton abstract class found here :

But now, I’m on a UIManager, and this approach doesn’t work anymore because this manager needs references to UI elements. I guess it comes to the “load themselves out of Resources/Addressables” part of your answer, but I couldn’t figure out what you mean or any resources to enlighten me.
Could you, or anyone ?

With Resources it works the same way as loading anything else via resources: Unity - Scripting API: Resources.Load

Just when the singleton Instance is accessed for the first time, it loads itself out of resources.

The same concept would apply with Addressables.