89

I see that we can initialize Variable in Awake() or Start() and Awake() will be called before Start().

When should we initialize in Awake and Start to have the best performance?

lysergic-acid
  • 19,570
  • 21
  • 109
  • 218
mdtuyen
  • 4,470
  • 5
  • 28
  • 50

5 Answers5

88

Usually Awake() is used to initialize if certain values or script are dependent on each other and would cause errors if one of them is initialized too late (awake runs before the game starts). Awake is also called only once for every script instance.

Let me quote the Documentation:

[...] Awake is called after all objects are initialized so you can safely speak to other objects or query them using eg. GameObject.FindWithTag. Each GameObject's Awake is called in a random order between objects. Because of this, you should use Awake to set up references between scripts, and use Start() to pass any information back and forth. Awake is always called before any Start functions. This allows you to order initialization of scripts. Awake can not act as a coroutine.

and about Start():

Start is called on the frame when a script is enabled just before any of the Update methods is called the first time.

Like the Awake function, Start is called exactly once in the lifetime of the script. However, Awake is called when the script object is initialised, regardless of whether or not the script is enabled. Start may not be called on the same frame as Awake if the script is not enabled at initialisation time.

Where the last part makes one big difference

To get to your question:

If the script is NOT enabled at the beginning of your game, and you don't need the variables to be initialized, start would be saving performance as awake() would be called regardless...
every variable would be initialized at the very beginning. At least that's the logical assumption I make.

Minzkraut
  • 2,149
  • 25
  • 31
  • 1
    I like this answer. Doing everything in `Start()` would mean that nothing gets *wasted* (i.e. initializing things that might never get used), however it might cause a bit of lag in the first frame, perhaps? – trojanfoe Jan 07 '16 at 10:25
  • 2
    Same could be said for awake, which would affect the loading time instead of the first frame. – Minzkraut Jan 07 '16 at 10:36
  • Yup. It's all a balance I guess. However I think delay in `Awake()` would be slightly less noticeable. – trojanfoe Jan 07 '16 at 10:37
  • Just to highlight the other important distinction that is independent of performance, all Awake() functions are guaranteed to be called before any Start() functions. – lfalin Jul 10 '17 at 18:07
  • 6
    Just as a note, Unity currently DOES NOT call Awake() anymore if the GameObject is inactive. Here is the flowchart for how the functions are called. https://docs.unity3d.com/Manual/ExecutionOrder.html – Harald Scheirich Oct 19 '18 at 21:47
  • @HaraldScheirich That flowchart lists "initialization" twice. Could you explain what the difference is since Unity no longer calls Awake() until the GameObject is active? – Prime624 Apr 23 '19 at 00:04
  • @Prime624 Start is called only if the script is enabled, but Awake is called only when the gameobject is active. Which means that Awake is called even when the script is disabled but the gameobject should be active. So like Minzkraut pointed out, use it to setup references to other scripts (example: linking highscore script in every level). – Anirudh Ganesh Jun 01 '21 at 19:55
18

This topic is well described in the official docmentation (Awake and Start).

This section describes why you might need two functions:

The Awake function is called on all objects in the scene before any object's Start function is called. This fact is useful in cases where object A's initialisation code needs to rely on object B's already being initialised; B's initialisation should be done in Awake while A's should be done in Start.

The difference between Awake and Start is that Start is called only when a script is enabled.

These two functions are called before the first Update method and there is no performance difference between them. I would say that Awake is used to initialize all objects (like a constructor), and Start is used to link the objects or do something before a game starts.

Sergii Zhevzhyk
  • 4,074
  • 22
  • 28
  • 1
    I like your suggestion to use `Start` to link objects. I would also add that there is additionality flexibility to modify script ordering to handle dependency linking on `Awake` by leveraging the [Script Execution Order](https://docs.unity3d.com/Manual/class-MonoManager.html). – Jeff Mandell Sep 05 '21 at 03:21
  • 1
    `The difference between Awake and Start is that Start is called only when a script is enabled.` Yes, just wanted to add: Have in mind that not even `Awake` is getting called if the `GameObject` is inactive – derHugo Dec 08 '21 at 14:20
7

Awake is the equivalent of the ctor. It is called when a MonoBehaviour is created, before any other method if the object is active.

Start is run the first time the MonoBehaviour is activated. This can be right after Awake or long after. This allows to perform actions that are related to the current state of the app or objects.

For instance, you create an enemy, in Awake, you place everything that is basic initialisation. Then, the enemy is deactivated at the end of Awake. Later on, the enemy is about to be activated but you want to make it red if player is having some specific weapon, then you do it in Start.

IMPORTANT: If a prefab is created and the game object is off by default in the prefab, the Awake is not called until set on. In the case of a pool creation where prefab may be off, the awake is happening first time the pooled object is activated.

OnEnable is similar to Start but happens on every SetActive(true) and on start if enabled. This can be a candidate for your enemy willing to change color over the level based on the player magna for instance.

Everts
  • 10,408
  • 2
  • 34
  • 45
4

There's not much difference in the performance. But I can tell you a difference between them.

Take a simple example. Say if you want to print "HELLO" in console even if you have not activated the script in inspector, using Awake() function, you can print it in the console. But if you had written the same thing in Start() function and the script wasn't activated, you don't get any output in the console. That's the difference.

Codes in Start() function get executed only if the script is activated while, codes in Awake() function get executed even if the script is not activated. Try it !

Manoj Hosmath
  • 41
  • 1
  • 5
2

I'd claim there is no real performance difference at all.

What Minzkraut stated

If the script is NOT enabled at the beginning of your game, and you don't need the variables to be initialized, start would be saving performance as awake() would be called regardless... every variable would be initialized at the very beginning. At least that's the logical assumption I make.

is only semi true. If you do everything only in Start the UX might be even worse since instead of one bigger lag when starting the app - which in my eyes is totally acceptable - it might lead to smaller but more lags during game play which I personally would avoid as much as possible.


In general it was already often explained in the other answers how and when Awake and Start are called and that basically it is "just" a timing difference.

For details refer to Execution Order of Events


Leaving disabled components and inactive GameObjects aside my personal thumb rule is

  • Use Awake for everything where you don't rely on any other component and references.

    E.g. set default field values, populate things using GetComponent etc

  • Use Start for everything where you do rely on other components such as accessing the results of GetComponent

    This way these other components supposedly did already receive their Awake call so they themselves are already linked up and ready to be used by others.

This solves timing and dependency issues in the most cases.

Where this is not enough you would start to tweak the Script execution order or use events.


And then there is another quite important difference in the use case of using Instantiate or AddComponent

  • Awake (and OnEnable except using Instantiate and the component is disabled) will be called right away during the instantiation and any code line after Instantiate will be executed after it is finished.

  • Start however will be delayed until the end of that frame (or until enabling if the component was disabled in Awake).

    This allows you to have enough time to use Instantiate and modify some field values before Start is called and can now base its behavior on the modified field values.

For example this

public class Example : MonoBehaviour
{
    private class X : MonoBehaviour
    {
        public int x = -1; 

        private void Awake()
        {
            Debug.Log($"Awake {x}");

            x = 12;
        }

        private void OnEnable()
        {
            Debug.Log($"OnEnable {x}");
        }

        private void Start()
        {
            Debug.Log($"Start {x}");
        }
    }
    
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("Instantiate");
            var x = gameObject.AddComponent<X>();
            Debug.Log("After instantiate");
            x.x = 42;
        }
    }
}

will produce the output

Instantiate
Awake -1
OnEnable 12
After Instantiate
Start 42
derHugo
  • 83,094
  • 9
  • 75
  • 115