Awake() vs Start() in Unity
Both of these are special event functions that Unity calls at predetermined times and are commonly used to initialize state in scripts (classes that extend MonoBehavior)
What's the difference between the two?
1. Awake() runs before Start() always for a script
2. Start() execution can be delayed since it can be run as a coroutine. Whereas Awake() cannot be run as a coroutine.
But why are there two functions for the same purpose?
The difference arises due to when Awake() and Start() run or doesn’t run.
Before we get into the difference, a small note to be kept in mind regarding wording associated with “turning a gameobject or script on/off”.
A gameobject can be activated/deactivated.
A script can be enabled/disabled.
A gameobject is activated/deactivated in the inspector by ticking/unticking the checkbox beside the name of the gameobject in the inspector.
A gameobject is activated/deactivated in code by calling the GameObject.SetActive() method or setting GameObject.active to true or false (although the latter is deprecated and SetActive() is advised to be used)
We can check if a gameobject is active by querying GameObject.activeSelf if it’s a root gameobject or GameObject.activeInHeirarchy if it’s a child gameobject. The reason we need to use a different field for child gameobjects is because a child gameobject can be deactivated if its parent is deactivated (even though the child itself isn’t deactivated). In this case, the child’s activeSelf returns true even though its deactivated in scene. Think of activeSelf as relating to local activation state of a gameobject without taking into account its parents state. Whereas activeInHeirarchy takes into account the parent’s state as well.
A script is enabled/disabled in the inspector by ticking/unticking the checkbox beside the script in the inspector.
A script is enabled/disabled in code by setting the scripts `enabled` field to true/false.
Now that we are done with that detour, we can tackle the actual question à What about when Awake() and Start() run/don’t run differentiates them?
To answer the above, let's consider a scenario. We have a gameobject and a script sits on the gameobject. The script has Awake() and Start() defined. Now there are two relevant possibilities we can consider:
Possibility 1: If the gameobject was deactivated as the scene loaded.
In this case, as the gameobject was deactivated, its temporarily removed from the scene and hence no code associated to the gameobject runs(including the code on the scripts attached to the gameobject).
Hence, neither Awake() nor Start() execute.
If the gameobject is then activated, then Awake() runs followed by Start().
Possibility 2: If the script was disabled (but the gameobject was activated) as the scene loaded.
In this case, Awake() runs irrespective of whether the script was enabled or not.
But Start() does not run. It runs as soon as the script is enabled.
In conclusion, Awake() sorta depends on the activation of the gameobject to run, whereas Start() depends on the script being enabled to run.
Another difference arises due to the fact that once Unity loads all the gameobjects in a scene à Awake() of all scripts run à then Start() of all scripts run.
So, by the time any Start() runs, all Awake()’s would’ve already run. We can use this fact as the basis to separate initialization code between Awake() and Start().
Generally speaking, initialize state of a script in Awake() and use Start() to access the state of one script in another script.
PS: Awake() and Start() run atmost once in the lifetime of their script. So even if we deactivate/reactivate a gameobject or disable/re-enable a script, Awake() and Start() will no longer run. Check OnEnable() and OnDisable() for that.