Awake -> Enable -> Start ---- not working for Singletons

Hello,
I’m creating a simple Singleton on Awake.

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

The problem is that this Singleton is not recognized in “OnEnable” function, but only in “Start” function.

Assuming the flow Awake–>Enable–>Start; I would think that everything after the Awake should be available, but it does not work.

Maybe someone could explain me better?

Follow with me.

Game starts.

Something loads this.

Awake fires

if statement is false, no Destroy()

instance set to this

time passes, nations rise, nations fall

something loads this a second time

OH CRAP! instance isn’t null, DESTROY THE OLD INSTANCE!

now set the instance to this new one.

Why are you doing any of that? It’s not a singleton, it’s just a static locator.

You can replace all of the above with:

void OnEnable() { instance = this; }
void OnDisable() { instance = null; }

and be done with it. This also enforces nobody touching it when it isn’t present / enabled.

Nothing above handles ANYTHING to do with lifecycles (eg DDOL).

If you are ACTUALLY concerned about lifetimes, then reach for ONE of the following two patterns, which I think I might already posted for you:

ULTRA-simple static solution to a GameManager:

https://discussions.unity.com/t/855136/6

https://gist.github.com/kurtdekker/50faa0d78cd978375b2fe465d55b282b

OR for a more-complex “lives as a MonoBehaviour” solution…

Simple Singleton (UnitySingleton):

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

public void DestroyThyself()
{
   Destroy(gameObject);
   Instance = null;    // because destroy doesn't happen until end of frame
}

There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

Beyond that, this might be of use: Here is some timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

1 Like

You probably mean the OnEnable method of a different class, right? Yes, that’s expected or at least not reliable depending on your script execution order. Awake and OnEnable are called right one after the other, script by script. Unity does not execute all Awake methods before all OnEnable are called. Both execute at the same time, just one after the other. They are called for different reasons. Awake is called because the object is active for the first time. OnEnabled is called because the object just has been enabled.

Again, Awake calls or OnEnable calls are not grouped across different scripts / script instances.

Just to make this clear. Assuming you have 3 objects (O1, O2, O3) and each one is having an Awake, OnEnable and Start method. The execution order may be something like that:

O2.Awake
O2.OnEnable

O3.Awake
O3.OnEnable

O1.Awale
O1.OnEnable

O2.Start
O3.Start
O1.Start

So if your singleton class is “O3”, it would not be set in OnEnable of O2 but it would be set in OnEnable of O1. You can control this order with the ScriptExecution order setting by placing your singleton before the normal time. However if you have multiple instances of the same class, those are still executed in the order they are loaded which can not be controlled at all.

2 Likes