Unity Lifecycle: Awake Vs OnEnable Vs Start
Where Do You Begin?
Introduction
When creating new C# scripts within Unity you will notice that the script is generated with two default methods, Start and Update. These methods are part of the script lifecycle and are called in a predetermined order. In this post we will discuss the initialization lifecycle and the three methods that make up the phase.
About
- Subject: Unity
- Objective: To discuss the difference between Unity lifecycle methods.
- Development Time: 8 min
Getting Started
Awake
The definition for Awake directly from Unity.
Awake: This function is always called before any Start functions and also just after a prefab is instantiated. (If a GameObject is inactive during start up Awake is not called until it is made active.)
Awake is the first thing that is called when an object is activated. This makes it useful for setting up the game object itself. It is not, however, the place to reference other objects as they may not be active yet.
OnEnable
The definition for OnEnable directly from Unity.
- OnEnable: (only called if the Object is active): This function is called just after the object is enabled. This happens when a MonoBehaviour instance is created, such as when a level is loaded or a GameObject with the script component is instantiated.
OnEnabled is unique because it is called every time the game object is enabled no matter how many times this happens. Put code here that needs to be executed each time the object is activated.
Start
The definition for Start directly from Unity.
- Start: Start is called before the first frame update only if the script instance is enabled.
Start is where you want to execute any code that relies on other game objects being awake and enabled.
Hierarchy
Unity gives us a great flow chart of the execution order in the documentation here. While this does help with visualizing the flow a single script goes through, another way to look at it is like so.
Initialization phase 1 | GameObject_1.Awake() GameObject_1.OnEnable() GameObject_2.Awake() GameObject_2.OnEnable() GameObject_3.Awake() GameObject_3.OnEnable() |
Initialization phase 2 | GameObject_1.Start() GameObject_2.Start() GameObject_3.Start() |
Frame Update |
As you can see, Awake will be called before the OnEnable method in the life cycle of a single object but there are no guarantees that the OnEnable method for one object will be called after the Awake method of another game object. The Start method will run after all game objects have had the opportunity to run their Awake and OnEnable though.
Testing
You can test this easily by setting up the following two scripts and attaching them to separate game objects. We will need to attach a reference for the second game object, Test2, to the first, Test1, inside the Unity editor.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
public GameObject test2;
void Awake()
{
Debug.Log("I am Test 1 Awake()");
}
void Start()
{
Debug.Log("I am Test 1 Start()");
}
void OnEnable()
{
Debug.Log("I am Test 1 OnEnable()");
}
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test2 : MonoBehaviour
{
void Awake()
{
Debug.Log("I am Test 2 Awake()");
}
void Start()
{
Debug.Log("I am Test 2 Start()");
}
void OnEnable()
{
Debug.Log("I am Test 2 OnEnable()");
}
}
If we start our game now we will see that the Awake and OnEnable methods for a single object run independently of other objects.
Start methods will run after Awake and OnEnable but remember they will only run once before the first frame update.
If we disable Test2 and run again you will see that none of the Test2 methods run.
Now if we change our update method of Test1 to enable Test2 we can see that all of the Test1’s methods including Start run before all of the methods of Test2.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
public GameObject test2;
void Awake()
{
Debug.Log("I am Test 1 Awake()");
}
void Start()
{
Debug.Log("I am Test 1 Start()");
}
void OnEnable()
{
Debug.Log("I am Test 1 OnEnable()");
}
void Update()
{
if(test2.active == false)
test2.SetActive(true);
}
}
We can modify the update method one more time to demonstrate that Awake and Start only run the first time Test2 is enabled.
void Update()
{
test2.SetActive(!test2.active);
}
And as expected Test2.OnEnable ran 462 times while Test2.Awake and Test2.Start only ran once.
Hopefully, that helps clarify when and where to use the initialization methods. If you found this helpful and would like to see more articles on the Unity life cycle please leave a comment below letting us know what you want to learn about next. As always thank you for stopping by. Stick around and check out more of our tutorials or posts like our piece on Unity Events and check out some of our published apps below.