Start vs Awake in Unity

In Unity by JohnLeave a Comment

When working with scripts in Unity, there are a number of special event functions that get called automatically by the engine at predetermined times.

Even if you’re very new to Unity, it’s likely that you’ve seen these automatic functions being used before.

Start and Update, which are added to new scripts by default, are common examples of such functions.

But they’re not the only ones.

In this post, I’ll be exploring two of the most well-used event functions in detail.

Start, which you will likely already be familiar with, and Awake, which may be new to you.

So…

What’s the difference between Start and Awake?

Start and Awake work in similar ways except that Awake is called first and, unlike Start, will be called even if the script component is disabled.

Using Start and Awake together is useful for separating initialisation tasks into two steps. For example, a script’s self-initialisation (e.g. creating component references and initialising variables) can be done in Awake before another script attempts to access and use that data in Start, avoiding errors.

In this post, I’ll be exploring the differences between Start and Awake in more detail so that you know exactly how to use them in your project.

Here’s what you’ll learn on this page

  • Unity’s order of event functions visualised
  • How to use Awake
  • How to use Start
  • Using Start and Awake together in Unity
  • On Enable vs Start in Unity

Let’s get started.

Advertisement

Unity’s order of event functions visualised

There are many event functions that take place when an application starts, runs and stops.

Unity calls these events in a specific order:

Unity Event Function Execution Order Visualised

Unity calls special ‘event functions’ in a specific order – this is it.

In this post, I’ll be focussing on the event functions used for initialisation (Awake, On Enable and Start). But you can find a full list of every event function (there are a lot of them) in Unity’s documentation here and an in-depth execution order reference here.

Start vs Awake

In Unity, you will often need to set up variables or make references to other game objects from a script before the game begins.

Even if you’re very new to Unity, you will probably have already seen one initialisation function before… Start.

    // Start is called before the first frame update
    void Start()
    {
        // Use this for initialisation
    }

If it looks familiar it’s because, along with Update, it’s added to every script by default.

Because of this, it’s probably where you are most likely to have added initialisation code or used it to set up variables and make references to other objects and components.

But there is another function, Awake, that may also come in useful.

Advertisement

How to use Awake

    void Awake()
    {
        // Awake is called even if the script is disabled. 
    }

Awake is called when the script is first loaded, or when an object it is attached to is instantiated.

It only gets called once on each script, and only after other objects are initialised.

This means that it is safe to create references to other game objects and components in Awake.

Which is actually a good way to use it, to create initial references between scripts and components that will be needed later on.

However…

You may run into errors if you try to use code in an Awake function that relies on code in another script’s Awake function.

This is because every object’s Awake function is called randomly, meaning you cannot guarantee that one object’s Awake function will be called before another or that any references you create in Awake will be ready to use by other scripts in Awake as well.

For example, consider two different objects getting references to each others’ scripts and components…

In Awake, Object A gets a reference to one of its own components while Object B gets a reference to Object A.

Object A

public class ObjectA : MonoBehaviour
{
  public Reference myReference;

  void Awake()
  {
    myReference = gameObject.GetComponent<Reference>();
  }
}

Object B

public class ObjectB : MonoBehaviour
{
  public ObjectA objA;

  void Awake()
  {
    objA = GameObject.FindWithTag("ObjectA").GetComponent<ObjectA>();
  }
}

Awake happens after objects are created. So, even though it’s the first event function called, both of the game objects and their components already exist and there are no errors.

So far so good.

However…

If Object B also tries to access Object A‘s component reference, it doesn’t work, causing an error.

public class ObjectB : MonoBehaviour
{
  public ObjectA objA;

  void Start()
  {
    objA = GameObject.FindWithTag("ObjectA").GetComponent<objA>();
    Debug.Log(objA.myReference.message);
  }
}

This can happen even if Object A‘s Awake function is called before Object B.

Null Reference Exception when using Awake in Unity

Trying to use a reference when it’s not there causes an error.

This is simply because Object A hasn’t made the reference to its own component yet and Object B is trying to access it.

So what’s the solution?

You already know it…

Advertisement

How to use Start

Start is called once, before any Update methods and after Awake. It works in much the same way as Awake, with a few key differences.

  • Unlike Awake, Start will not be called if the script is disabled
  • Start can be called as a coroutine

This means that code that is placed in Start can be delayed.

How to delay Start in Unity

Start only gets called on a script if the component is enabled.

This means that you can manually delay Start from being executed by keeping the script disabled until you need it.

Start can also be called as a coroutine.

This means that you can delay operations called in Start to take place after a predetermined delay. For example, 5 seconds.

Simply change the default ‘void’ return type to ‘IEnumerator’. Like this:

IEnumerator Start()
    {
        yield return new WaitForSeconds(5);
        // Do something after 5 seconds
    }

However…

The most powerful way to use Start is with Awake.

Using Start and Awake together in Unity

In many cases, you may be able to do all of your initialisation in only Start or Awake, which is perfectly fine if it works for you.

However,

Using Start and Awake together offers you two initialisation steps, one after the other.

This means you can separate the code that creates references between objects and components from the code that actually uses them to do something, which makes it easier to avoid null reference errors when initialising scripts.

And while there’s no one rule for how to do this, it can help to make a decision on early on about what kind of code will take place in Start and what kind of code will happen in Awake.

For example…

One approach is to use Awake to initialise an object’s own references and variables, (e.g. creating the connections between the object and its own components) while then using Start to use or create references to other objects and their components.

This approach prevents a script from trying to use to a reference that doesn’t exist yet, such as in the example earlier or when using functions that don’t work properly when called from Awake, such as trying to call Set Float to change an Audio Mixer parameter (it just doesn’t work).

Exactly how useful this will be for you depends entirely on your project and how it is structured however, generally, it’s good practice to use both Awake and Start when initialising scripts in order to avoid errors.

Lastly, there is one more initialisation function that’s worth mentioning and that works in a similar way to Start, On Enable.

Advertisement

On Enable vs Start in Unity

On Enable and Start both get called when the script component is enabled, whether that’s manually from a script or automatically at the beginning of the game, with On Enable getting called first.

So what’s the difference between On Enable and Start? And which should you use?

While Start will only ever be called once, On Enable is called every time the script component, or the object it’s attached to, is enabled.

Because of this On Enable isn’t usually suitable for initialisation tasks that only need to happen once.

Unless… that’s actually the behaviour you want.

For example, when object pooling.

Object pooling is a technique to avoid repeatedly destroying and instantiating objects that are frequently re-used, such as projectiles and enemies, by simply disabling and re-enabling them again in a new position. This is often more efficient, saving CPU and memory.

When using an Object Pool, code that you might normally put in Start can, instead, be placed in On Enable. For example, setting the enemy’s health to its starting value in On Enable will mean that the enemy gets ‘set-up’ correctly every time it’s re-enabled.

Now it’s your turn

Now I want to hear from you.

How are you using Start and Awake? Do you follow a simple guideline to separate what code goes in which function?

Or maybe you’re only using one of them. If so, how’s that working out for you?

Whatever it is, let me know by leaving a comment below.

Image attribution

Abstract photo created by starline – www.freepik.com

by John Leonard French

Game audio professional and a keen amateur developer.

Popular Posts

Advertisement

Leave a Comment