OnEnable, Awake, Start order

I use a “framework” class that is set to run before all the other scripts (-300).
This class has an Awake method. I also use another normal monobehaviour which defines the OnEnable method.

Once the application runs, the OnEnable of the second monobehaviour is called before the awake of the framework class. Is this the intended behaviour?

It’s rather complicated.

[

Update 5.1.1: I didn’t re-test everything, but here is what seems to be fixed/different in both 5.x and 4.x (tested 5.1 and 4.6), as opposed to 3.5:

  • The bug that the user-defined execution order is ignored if one (but not all) script has an “OnEnable()” function (=see “EDIT3” below) seems to be fixed.
  • OnLevelWasLoaded() is no longer called before Awake(), and always after OnEnable()
  • The execution order of OnLevelWasLoaded() is still arbitrary and cannot be user-defined
  • OnEnable() is no longer called in successive levels if DontDestroyOnLoad is active.

]

A simple test with 3.5.2 revealed, most concurrent functions (well, at least the ones I tested: Awake, Start, OnEnable, FixedUpdate/Update/LateUpdate) abide by the execution order defined for the scripts. The execution order of OnLevelWasLoaded is not affected by that, and therefore cannot be influenced by the user. This could be considered a bug.

The order of the four methods of a script related to initialization is always:

  • Awake()
  • OnEnable()
  • OnLevelWasLoaded() // (only on scene changes)
  • Start()

However, if your script was disabled in the first place(via Script.enabled=false), this order changes to:

  • OnLevelWasLoaded() // is now called first, before Awake()! (only on scene changes)
  • Awake()
  • [OnEnable()/Start() are not executed until the script is actually enabled]

In addition, note that Awake() and OnEnable() calls are connected/interleaved. Meaning, assuming a particular, user-defined execution order A and B with A*<*B,

  • each individual script of type A will execute its Awake(), immediately! followed by its OnEnabled()
  • then all scripts of type B will do the same
  • then all OnLevelWasLoaded() will be executed, in a (presumably) fixed but unpredictable order (assuming this scene was freshly loaded - otherwise this step is skipped completely)
  • then all Start() will be executed, in the order A,B

In particular, this means that OnEnable() of type A will be executed before Awake() of type B, while OnEnable() of type B will be executed after Awake() of type A. This overview explains it more clearly:

  • Awake() of Type A, instance 1
  • OnEnable() of Type A, instance 1
  • Awake() of Type A, instance 2 // order of instances cannot be influenced
  • OnEnable() of Type A, instance 2 // order of instances cannot be influenced
  • Awake() of Type B
  • OnEnable() of Type B
  • OnLevelWasLoaded() of Type ? // order cannot be influenced
  • OnLevelWasLoaded() of Type ? // order cannot be influenced
  • Start() of Type A
  • Start() of Type B

EDIT: Hm, this is a total mess. If DontDestroyOnLoad() is activated for such a script, this will get even more complicated, and the order changes yet again to:

  • [Awake() is never called again, only the very first time]
  • OnEnable()
  • OnLevelWasLoaded() // as opposed to being called before OnEnable(), when DontDestroyOnLoad() is not activated
  • [Start() is never called again, only the very first time]

EDIT2: In addition, when DontDestroyOnLoad() is active, the user-defined execution order is no longer abided by!, neither by OnEnable(), nor by OnLevelWasLoaded().

EDIT3: WAH! I’m gonna stop testing now, this is a neverending story… As @Noisecrime noticed, there is actually another bug, where user-defined execution order is overriden if the script has an OnEnable() function!

Script A has OnEnable, Script B has not:

  • Awake() of Type A
  • OnEnable() of Type A
  • Awake() of Type B

Script B has OnEnable, Script A has not:

  • Awake() of Type B
  • OnEnable() of Type B
  • Awake() of Type A // after Type B!

From the sound of it, this is the ‘OnEnable’ bug with script execution order. That is I suspect your ‘framework’ script does not have an OnEnable method in it, in which case for some odd reason it will get trumped in execution order by the scripts that do, despite any ordering you add to the script execution.

To fix this issue, simply add an OnEnable method to your framework script.

OnEnable and Awake are called when the objects / script instance is created. They are propably called from the internal constructor. They are even called before Instantiate returns. There is no way to influence when awake / OnEnabled is called on scene objects. The execution order you can set in Unity only influences the Unity generated events like Start, Update, LateUpdate …

Avoid code in Awake which relies on other object. Start is made for this purpose. Start is called after all scene objects are created and all Awake function has been called. In general you should use Start to initialize object dependencies.

The manual is not that clear about it. It mentioned OnEnable after Awake in list order but it only said clearly that all Awakes will be called before any Start. again in summary it only shows Start and Awake and not OnEnabled. but for Awake says it will be called After Instantiation and for OnEnabled it says after object becomes enable so theoratically Awake should be sooner than OnEnable.

I just submitted another strange bug, where the scripting order gets violated. If you have the following setup in your hierarchy (where “Prefab” is any prefab instance):

GameObject
   +- Prefab
      +- GameObject
         +- Prefab
         +- ObjectWithUnmportantComponent
ObjectWithImportantComponent

Then the component of “ObjectWithUnmportantComponent” gets executed first, even if it has a script order number higher than a component in “ObjectWithImportantComponent”.

Some of the info in previous is now old and outdated. Please refer to this flow chart for an accurate / up-to-date flow:

Source: Execution Order of Event Functions

Gah! Yeah, this order stuff is incredibly ugly. Just wanted to chime in with a couple of additional facts about Awake and OnLevelWasLoaded (as of 5.2):

Awake is not called if the gameObject that is on is inactive. This is unintuitive since Awake is called if the script itself is enabled.

OnLevelWasLoaded does not seem to be called for the first scene objects are in. Or at least in the Editor they are not called in the first scene. Less sure about the details here than for Awake - if anyone has a similar experience, let me know in the comments.

All of this wackiness makes me wonder if some other non-Start/Awake solution is needed…

Check this link, it provides execution order for all functions of unity

I hope it helps.