The term “Singleton” comes up rather often once you’re past the first few hurdles in coding for Unity, and upon researching it, you likely have seen anything from it being a really bad thing to it being that one solution you absolutely need.

Since it seems that a large part of the Unity community is using the term a bit imprecisely, here’s a short article that explains what a singleton is… and what it isn’t.

The singleton pattern

The term “singleton” was coined by a book called Design Patterns by the “Gang of Four”. It’s a very influential book that explains how code doesn’t have to be written entirely from scratch, but can use specific patterns to implement solutions for recurring problems. When you build a house, you don’t make a hole in the wall and put some glass in it – you build a window. If you use patterns like these, people don’t have to understand your code from the ground up, but they can see the bigger picture you made from parts they already know.

One of the patterns that are described in the book is the singleton pattern. To showcase it, here’s a simple singleton implementation:

public class Player { public readonly static Player singleton; private Player() { } public void Die() { // do death stuff } }

In short, this class has the following properties:

A static field references a single instance of this class. A private constructor makes sure no other class can create an instance of this class. The only instance is under the control of the class itself. This example code is missing the initialization part for simplicity reasons. By accessing the “singleton” field, you access the singleton object.

There are multiple parts of this code that can look different. For example, instead of exposing the static variable, you can use static methods that allow limited access to the object. The initialization can happen in multiple ways, too. But the core idea stays the same: A singleton class is a class that makes sure only one instance of it exists at any given time.

Why singletons are bad

The pattern was heavily criticized and is often called an “anti pattern”. At least one of the authors voiced that it wouldn’t be part of the book anymore if it was written today.

The pattern generally doesn’t make much sense as all it does is to move the class’s functionality into the global scope. Instead of having to get the reference to the object somehow, we can access its methods and fields through the static wrappers we write – or we get the reference from the singleton.

Instead of doing this, we could just make the class static and have no instance at all, with the class itself doing the job:

public static class Player { public static void Die() { // do death stuff } }

The only thing we might lose here is the chance to pass around a reference to the singleton instance – but why would we want that, given that we always know where it is anyway?

So when you talk to a programmer who studied design patterns, you’ll usually hear that using it is a bad idea, and that notion has gotten through to Unity developers who, if they didn’t study design patterns, might tell you to not use singletons without knowing where the issue is.

The Unity pseudo-singleton pattern

In Unity, we have a very similar pattern that is often referred to as “singleton”. It looks like this:

public class Player : MonoBehaviour { public static Player singleton { get; private set; } private void Awake() { if (singleton == null) { singleton = this; } else { Destroy(gameObject); } } public static void Die() { if (singleton) { // do death stuff } } }

It looks very similar to the singleton pattern, as it has the following properties:

A static field references a single instance of this class. Since we cannot keep Unity from creating GameObject s when the scene starts, we have the object destroy itself if an instance already exists. The “singleton” field allows access to the component instance, so we can call Player.singleton.Die(); from anywhere in the code.

Again, there are the same variants of this, like hiding the static field and creating static methods for controlled access. But either way, this pattern does not exactly come with the same cons as the actual singleton pattern, which is why I don’t like to call it that. After all, patterns are meant to immediately tell you what you’re dealing with, and when a programmer hears “singleton”, the word rings bells that don’t belong here.

The issue with the singleton pattern is that turning your class into a static class is a non-problematic, working alternative to it. If your object is the only one of its kind, and you have static access to it, then just have the static class itself replace your object. There’s no need for an object instance to be involved.

When talking about components in Unity, this is not the case. There are things that components can do that cannot be done in a static context. There’s the GameObject and the other components next to ours that might be of interest. And without a component instance, we’re unable to receive Unity’s events, like Update. And lastly, we cannot set our favorite values in the Unity Editor if our class is static.

For all of these reasons, it makes sense to have a pattern like the “Unity pseudo-singleton”, as I like to call it. There’s plenty of things static classes cannot (easily) do in Unity, and with this pattern, we combine the powers of an actual instance with the easy access provided by a static variable.

Player.Die();

Pseudo-singletons suck, too…

Now it sounds like we’re in the clear and what many Unity devs call a “singleton” is actually totally okay. In fact, I’d even say it is. The pseudo-singleton pattern allows you to implement a component meant for a single, important object in your game, like the player or the finish line. They make sure “the player” is known to the entirety of the game, which allows objects to check whether the collider they found belongs to the player, or to trigger an event that reaches from one corner of the game logic to another, like the player character dying when it runs out of time.

It’s only when your games become more complex and your workflow becomes more sophisticated that you start to stumble over the problems this pattern provides. Instead of going much into detail, I highly recommend this talk by Ryan Hipple at Unite Austin 2017.

This talk contains information on why the pattern is problematic for good architecture and comes with an approach to replace the pseudo-singleton pattern.

Just a short example of one of the many issues you can run into.

Imagine a player character with a health bar. The player (health) component is a pseudo-singleton and thus allows the health bar to get and then display the player character’s health points with a simple line:

image.imageFill = PlayerHealth.healthPoints / PlayerHealth.maxHealth;

The class might well be more sophisticated than this, perhaps by adding some visual and sound effects to health changes.

Next, you want to create a boss fight and notice that the health bar script can’t really help you here, because it is hard wired to use the player character’s health. So you need another script to do the exact same thing, except for another health value. Or you create some ugly if/switch statements within your health bar class to determine what to display.

Ryan’s talk goes more into detail about the issues you impose on yourself by using this pattern, so definitely watch it!

…but you can use it anyway

So, does that mean you shouldn’t use this pattern either? DECIDE ALREADY!

At this point, this topic isn’t about right or wrong, but starts to be a question of your context. The pattern definitely comes with downsides that increasingly make your life difficult while your project grows. If you can avoid it, perhaps with ScriptableObject s, I’d recommend doing so in most cases.

However, if avoiding this pattern is a problematic hurdle for you, or your project’s code base will never be very complex, the pseudo-singleton pattern is an available option that does come with its advantages. If you ask me, feel free to use it as long as you keep in the back of your head that sooner or later, you should abandon it for most cases. Once you’re there, I recommend working through Ryan’s approach. I’ve put a lot of work into creating an implementing package with a long and detailed manual that helps you understand how to use it just right; you can get it in the Asset Store.