Singletons in Unity

Singletons in Unity (done right)

In Unity by John French24 Comments

Even if you’re new to Unity, you probably already know that Singletons can be a controversial topic.

You might have heard that they are useful, but also never to use them.

And that, if you do, your game will be difficult to manage as it gets bigger.

However…

While there are good arguments for not using singletons, for a beginner, who’s just trying to get their game finished, singletons can be a useful and simple way of connecting scripts.

And it’s not just beginners who find singletons useful, as there have been many Unity developers who have been happy to use singletons in their games as well.

So what’s the deal with singletons?

Are they helpful or harmful?

And is it ok to use one in your project?

Well, that depends…

Generally speaking, many of the problems that can occur from using a singleton are caused by how you choose to use them in your project, not by the singleton itself. 

Some singleton methods can be more problematic than others but exactly what issues you’re likely to run into depends on your specific project and what you have planned for it.

This is because, a lot of the time, the effect of using a singleton may only start to become clear later on, as your project grows bigger or when you try to change something.

Unfortunately, this means that the risks of using a singleton can be unclear, but don’t worry…

In this article, I’ll show you some of the different ways you can use singletons to make building your game easier, along with some of the potential risks involved, so that you can make the right decision about whether or not to use singletons in your game.

Here’s what you’ll find on this page:

So, what even is a singleton?

What is a singleton in Unity?

Generally speaking, a singleton in Unity is a globally accessible class that exists in the scene, but only once.

The idea is that any other script can access the singleton, allowing you to easily connect objects to important parts of the game, such as to the player or to other game systems.

Which can be useful for connecting unrelated objects and scripts to global systems, such as an audio manager, for example.

So how do they work?

A singleton in Unity is a normal class that can be added to an in-game object.

What’s different about a singleton, however, is that the class holds a public static reference to an instance of its own type.

Like this:

public class Singleton : MonoBehaviour 
{
    public static Singleton instance;
}

The static reference is what makes a singleton globally accessible.

Making a variable static means that it is shared by all instances of the class, meaning that any script can access the singleton through its class name, without needing a reference to it first.

Like this:

Singleton.instance;

This means that any public methods or variables that exist in the singleton class can be accessed by other scripts in the game easily.

However, because any script can access it, it’s generally a good idea to protect the instance variable with a property, which simply means that it can be read by other scripts, but it can only be set from within its own class.

Like this:

public class Singleton : MonoBehaviour 
{
    public static Singleton Instance { get; private set; }
}

While the reference to the script is static, meaning that it is the same in any and all instances of the class, the instance that it points to is not.

Meaning that, while the reference can only ever point to one instance of the script, it’s possible to have more than one instance of the singleton in the scene.

Which is why it’s important to make sure that there is only ever one instance of the singleton by checking to see if the static reference, if there is one, matches the script instance.

Then, if it doesn’t match, the script knows that it’s a duplicate and it can delete itself.

Like this:

public static Singleton Instance { get; private set; }
private void Awake() 
{ 
    // If there is an instance, and it's not me, delete myself.
    
    if (Instance != null && Instance != this) 
    { 
        Destroy(this); 
    } 
    else 
    { 
        Instance = this; 
    } 
}

These are the two basic requirements for a singleton.

A globally accessible class, but with only one instance.

But why would you make a singleton, and what can you do with them?

Why use a singleton?

Singletons can be very convenient because they allow you to connect parts of your game more easily.

For example, you could use a singleton to make the player’s position publicly accessible to enemies, or use one to expose the player’s health to the UI.

Like this:

float healthBarValue = Singleton.Instance.playerHealth;

Or, you could call a sound effect function on a singleton from any script in the game.

Like this:

Singleton.Instance.PlaySound(clipToPlay);

So long as the variable or function exists on the singleton, and it’s publicly accessible, other scripts will be able to use it without you needing to set up a reference to it first.

Which can make connecting the different parts of your game much easier.

However…

While singletons can be easy to use, they can also cause problems.

Using a singleton to solve a problem you have right now, might create a different problem later on, so it’s worth being aware of what could happen if you choose to use a singleton in your project.

So, what’s the worst that could happen?

What’s bad about singletons?

Generally speaking, singletons can make it difficult to manage your project as it gets bigger.

They can make your project harder to change, more difficult to extend and can cause problems with testing. 

If you’ve looked into using singletons at all, then you may have already heard some of these objections, but what do they actually mean for you?

What, specifically, could go wrong when using a singleton?

One of the biggest risks with singletons is, by design, the very thing that makes them convenient in the first place, global access.

For example, allowing every script access to a game manager singleton can be extremely useful.

So, how is that a problem?

I’ll explain…

Game manager singletons

One of the main benefits of using a singleton in your project is to avoid needing to tightly connect important scripts, such as game managers, with the many different objects that may need to access them.

Such as an audio manager, for example.

It would usually be bad design to try to connect every single object that wanted to play a sound to the audio manager script manually.

Likewise, it could be very bad for performance to try to find the audio manager in the scene every time a new object that might need it is created.

For that reason, an audio manager singleton can make a lot of sense.

So, let’s say that you do exactly that, that you create an Audio Manager singleton with a public Play Sound Effect function.

Like this:

public void PlaySound(AudioClip clip)
{
    audioSource.PlayOneShot(clip);
}

Now, whenever you want to play a sound, you can simply call the audio manager and pass in a sound effect.

Like this:

public AudioClip soundEffect;
void Start()
{
    Singleton.Instance.PlaySound(soundEffect);
}

Simple and convenient…

But is there anything wrong with this method?

Will using it cause you a problem?

For what it aims to do… no there’s nothing really bad about using a singleton in this way.

However…

The problem you’ll probably run into when using a singleton like this is if and when you decide you need to change how sound effects are triggered.

For example, you might start to use this method, adding a sound effect trigger anywhere you need to, calling the sound effect function from many different scripts.

Which, depending on the size of your game, could be tens or hundreds of different places, all calling the script in the exact same way.

Game Manager Singletons visualisation

Singletons can be used to give many different objects easy access to game systems, which can be both good and bad.

Then, as you start to add sounds to your game, you might notice that some are louder than others, while others are beginning to sound repetitive. 

So let’s say that you decide that you’d like to make a sound’s volume adjustable when you trigger it, so that different clips can be played at different levels and that you’d also like to add in some extra variations of some sounds when they’re triggered, to prevent them from becoming repetitive.

In isolation, these are simple features that are relatively easy to create.

Except that doing it now will probably be a difficult task, because every sound trigger in the game has a direct line to the audio manager and simply calls the function as it is, passing in an audio clip reference and nothing else.

Which means that, to change how the audio manager works now, you’d need to change every script that calls it too.

Which could be a lot of work.

Modular event triggers in Unity

When using singletons, it’s easy to lock in certain functionality early on, making things difficult to change later.

Events, however, by design, can be a useful way of changing the response to something that happens in a game, but without changing what triggers it.

For example, it’s possible to make a basic events system that would allow an object, any object, to trigger a sound effect event, but where the response to that event, such as what sound is played and how it’s handled, takes place on the audio manager and can be easily changed without needing to change what triggered it.

While this is also possible to do with singletons, events can be more forgiving when you want to change something later, since the trigger can be more easily removed from the response.

While having to change what a singleton does after you’ve made it isn’t easy, it’s not necessarily a major issue.

For example, while it would definitely be difficult to change the sound effect function at a later date, it wouldn’t be impossible.

However, knowing this, it can be helpful to treat every public function and variable that you expose to other objects using a singleton as if it’s something that can’t be changed.

Then, by building in the functionality you’re expecting to need early on, you can minimise the risk of needing to change how it works later.

An audio manager is, potentially, a good fit for a singleton because global access and an in-scene presence make using it easier.

Put simply, the main benefits of using a singleton match the problems of the task.

However…

Just because a singleton seems like a good solution to a problem, doesn’t always mean that it will be.

And, just like before, how you choose to use a singleton now, will affect what you can do with your game later.

Which can be especially true when using a player singleton.

Player object singletons

One common use for singletons is to expose certain characteristics of the player to other scripts in the game, such as the player’s position or their current health.

Which makes a lot of sense when you think about it.

After all, just about every object in the game is probably going to respond to the actions of the player in some way, so making it easy for them to access the player and their scripts seems like a good idea.

But, what problems could be caused by using a player object singleton?

Player singleton visualisation

A player object singleton can be used to give every object access to the player, but it’s not without its drawbacks.

Generally speaking, deciding when it’s ok to use a player object singleton can be a lot like deciding whether or not it’s ok to use a static variable.

Using a static variable, which is essentially a global variable, is generally fine, so long as you only intend to ever have one variable of that type in the game. 

Singletons have the same vulnerability.

Because scripts that need to reference a singleton do so directly, each script, essentially, has a tight connection with the player.

Meaning that adding a second player at a later time could be extremely difficult or impossible, depending on how tightly integrated the player singleton is with scripts that need to access it.

Generally speaking, using a singleton to manage a unique, individual object, such as a player, carries more risk than using one to manage a game system.

And while it may not be a problem for you and your project now, using a singleton in this way can cause significant issues further down the line if you’re not absolutely sure what your game is going to be like or what features you might like to add in the future.

Scriptable object variables vs singletons

Normally, a script’s variables are explicitly typed out, meaning that, if you want a health bar to check the health of the player, for example, you will often need to reference a specific instance of that player’s health script and variable.

While singletons make this easier to do, they don’t change the fact that you’re still directly referencing a specific script on a specific object in the scene. If you ever need to change it, you’ll have to rewrite the code, which is why singletons can make it hard to refactor code later.

Scriptable object variables, on the other hand, work in a different way. They can be used to reference a variable type instead of a specific variable.

Which means that, instead of referencing the player’s health, they can, instead, reference a player’s health. The health variable can be easily swapped out in the Inspector for a variable of the same type but on a different object. Meaning that you could, for example, create a whole second player, with their own health bar, and all you’d have to change is which health variable type the health bar was reading from.

Which is as simple as swapping out the scriptable object in the Inspector, without changing the script.

Using a singleton can sometimes make managing your project more difficult as the references you use will often be direct, explicit references to singleton objects, such as the player or some type of game system.

What’s more, if you’ve gone down the route of using singletons, you may have multiple singleton systems in your game.

Which can make it very difficult to keep track of which script is doing what, since any script can do anything.

However, it’s possible to limit some of the problems that can be caused by global system access, while still leveraging the benefits of using a singleton in the first place.

For example, with a master singleton, that provides access to other game systems through a single point of access.

Master singletons (service locators)

This approach, while it uses a singleton, is technically a different design pattern called the Service Locator, which uses a gateway singleton to manage access to multiple other game systems.

Which can be useful when you want the functionality and ease of access that a singleton can provide, but with an extra layer of control.

Master Singleton visualisation

A “service locator” style singleton can be used to provide access to other, non-singleton scripts.

This works by adding a single master singleton in between your game’s systems and the objects that might want to access them.

Like this:

public class Singleton : MonoBehaviour
{
    public static Singleton Instance { get; private set; }
    public AudioManager AudioManager { get; private set; }
    public UIManager UIManager { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(this);
            return;
        }
        Instance = this;
        AudioManager = GetComponentInChildren<AudioManager>();
        UIManager = GetComponentInChildren<UIManager>();
    }
}

In this example, the audio manager and UI manager are child objects of the singleton.

Setting up a master singleton

When using this method, you’ll need to set up the singleton’s references using Get Component in Children, because read-only references can’t be set in the Inspector.

Also, because a destroyed component is deleted on the next update loop, the Get Component calls will still take place even if the script is going to be removed. 

Which is why it can be helpful to use the return keyword if the script is going to be destroyed, to stop the function progressing any further if it is a duplicate.

You will then be able to access the individual systems of your game via a single entry point, by referencing the singleton instance and its subsystem.

Like this:

Singleton.Instance.AudioManager.PlaySound();

While this doesn’t prevent the problems that can be caused by needing to change your code later, it does add a layer of abstraction between your singleton systems and the objects that might want to access them.

Which can make it easier to build your game in a way that is less challenging to extend.

How to use a master singleton

In this video from Thousand Ant, Sam Eng describes how he used a master singleton when developing his game, Zarvot.

What’s the right way to use a singleton in Unity?

While there’s no one right way to use a singleton, the problems that could be caused by using one usually depend on your project and what you plan to do with it.

This is because the risks of using a singleton are more to do with how you choose to use it and less about the singleton itself.

For example, using a player object singleton when you might want to add extra players later will probably cause you major issues.

While allowing global access to a file save system could cause problems if two scripts unknowingly try to save the game at the same time.

And building your singletons before you know what you want to do with them can make it much harder to update them later when something needs to change.

However…

There may be times when using a singleton makes a lot of sense.

Especially if it’s going to mean the difference between releasing your game or not.

So, while many people may steer you away from singletons, and while there are definitely good reasons not to use them, if you understand the risks and use them carefully, they can be very useful as a tool to help you to manage your game more easily.

Now it’s your turn

Now I want to hear from you.

Are you using singletons in your game?

Have they helped you, or have they made your project more difficult to work with?

And what experience do you have with singletons that could help someone else decide if using them is right for their project?

Whatever it is let me know by leaving a comment.

by John Leonard French

Game audio professional and a keen amateur developer.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

My favourite time-saving Unity assets

Rewired (the best input management system)

Rewired is an input management asset that extends Unity's default input system, the Input Manager, adding much needed improvements and support for modern devices. Put simply, it's much more advanced than the default Input Manager and more reliable than Unity's new Input System. When I tested both systems, I found Rewired to be surprisingly easy to use and fully featured, so I can understand why everyone loves it.

DOTween Pro (should be built into Unity)

An asset so useful, it should already be built into Unity. Except it's not. DOTween Pro is an animation and timing tool that allows you to animate anything in Unity. You can move, fade, scale, rotate without writing Coroutines or Lerp functions.

Easy Save (there's no reason not to use it)

Easy Save makes managing game saves and file serialization extremely easy in Unity. So much so that, for the time it would take to build a save system, vs the cost of buying Easy Save, I don't recommend making your own save system since Easy Save already exists.

Comments

  1. thank you so much sir for this topic,i hope you will post new tutorials as it seems that you stopped for a while.

    1. Author

      You’re welcome. Don’t worry, more tutorials are on the way, just working on a special project first. If you’re subscribed to the newsletter, you’ll hear about it soon.

  2. keep it up man, love your way of explaining difficult topics!

  3. Thank you. Every time you post a new article. The content is amazing. I think it’s just a little bit but there’s still a lot I haven’t learned. Thank you

  4. Great blog, thank you!
    I’m quite new to gamedev and singleton has been useful for most cases but sometimes i scratched my head trying to find where is the function being called haha.

  5. I’ve heard of singleton some time ago and today I was wondering if it’s a good idea to use singleton in a small project I’m working on. Now I think I’ll use it. Thanks for the great explanation of the topic 🙂

  6. Nice article. I do have a question about assemblies though. Won’t using a master singleton that has GetComponentInChildren cause your master singleton’s assembly to depend on tons of scripts, essentially making assemblies unusable?

    My project is big enough that assemblies have to be employed to speed up compile times.

    1. Author

      Thanks! Unfortunately, I don’t have an answer for you on using Singletons with assemblies. However, singletons are pretty common in Unity, so someone in the forums can probably help you with this.

  7. Hi John. Great article (as are all your articles – you’re very talented at explaining complex concepts in a simple, yet still detailed, way).

    For the master singleton, would the sub-systems also be singletons? Or is the idea that the master singleton is the one and only singleton, and its sub-systems are just normal game objects and classes?

    1. Author

      Thanks Adam, so yes in that example only the Master is a singleton and the systems it links to are just regular scripts.

  8. great post!!
    i was drawing a class diagram. but i conflict so many singletones.
    for example, SoundManager, UIManager, DataManager, NetworkManager, ResourceManager, PoolManager,,

    when I was thinking of make similar master singletone, i saw this post.
    I will take note. thank you.

  9. Really great article!
    I’m making Portfolio for my game and was having difficulties for making design patterns. I always thought using singleton is against OOP so never to use them. but I guess understanding when to use it, I can use some of it for my project. It would greatly reduce my time.

  10. Thanks again.

    I can say from the other hand that also not using them can get things really nasty with endlessly fetching the same objects/scripts all over…

    Intuitively (as I never tried it) while understanding the risks at scale, I think that a Singeltone + paranoia (just a bit) would end up being much easier to manage if I’ll include some “collision detection” in it for all the incoming requests.

    But who knows, gonna be fun trying anyhow

  11. Hello! Thank you for your article. Could you please tell, alternatives to Singleton pattern? I’ve read an article about Service Locator and it was stated there that it could also lead to major issues. Right now I am sort of paralyzed being new to Unity and cannot make up my mind about how to approach my project. Is there a safe pattern of organizing elements of the game?

    1. Author

      Hi Alex, I’m not much of an authority on the different design patterns (try this site for that) but in my limited understanding I think that a good way to do it as a beginner, is to think about what it is you’re trying to build, pick an approach that will probably work, based on the strengths and weaknesses of different methods, and what other people have done to make similar games, and then just run with it.

      Realistically, you might end up using parts of one pattern to do one thing and parts of another to do something else but, generally, you’re not going to really know if something is working for you until you start doing it. And while I imagine that strict adherence to a framework is probably pretty important to big teams and large-scale projects, if you’re on your own, and especially if you’re new to Unity, it’s probably better to just focus on what works for you and what kind of works for the project and, so long as it won’t cause you big problems later, try not to overengineer it. Hope that helps!

Leave a Comment