The singleton post – making a Singleton in Unity3d with inheritance

singleton unity3d inheritance

You already know what a singleton is? See how to do it by inheriting from a SingletonBehaviour<T>, skip to “How to singleton”

Sometimes when programming you are just reinventing the wheel. And by sometimes I mean all the time. Basically every problem a programmer faces is an already solved problem from an algorithmic perspective. Either that or you’d have better refused that job unless you are in academy.

So why not to look at all the already found solutions and use the ones matching your problem? The best solutions to the most common problems have been codified a long time ago, both for programming in general (ever heard of the Gang of Four?) and for game programming in particular.

Today I’ll talk about one of these standardized solutions, the most famous one: the Singleton.

What’s “singleton”?

one-way-street-362172_1920

A singleton is a class that you want to make sure is unique and globally accessible. This means that there’s only one in your scene and that it’s accessible from everywhere and everything.

Of course in Unity you won’t have a class floating in nothingness, althought you could do so with a static class. In Unity you want to use that sweet inspector to tweak the singleton’s variables, so you want to make it a component to an object.

When to singleton

gummibarchen-359950_1280

There’s a lot of cases in which a Singleton is just a good idea. For instance since you only have one touch input source on a mobile device, it would be a good idea to have a singleton deal with it.

Also, if you are in need of managing the timing of all the enemy attacks in your musical shump a singleton would be the best candidate to handle the coordination. You need a lot of slowmotions and want to check if there’s overlap? Get a singleton to do that!

You should ask yourself these two questions to check if you need a singleton:

  • is this a thing that must not be duplicated or otherwise there could be problems?
  • is this a thing that I want to have easily accessible from everywhere?

When not to

Since the singleton is very quick to implement (and with this inheritance-based approach you’ll need just a few characters to do so) it’s easy to over-use it and to add useless singletons.

An example is the case where you make a singleton EnemyManager and an Enemy script, where the latter only has some data and the former’s only aim is to extend the Enemy with methods. In that case is better to just add the methods in the Enemy script.

To check if you really need that singleton ask yourself:

  • do I need to hold some information in this class or it’s just methods?
  • can’t I just do the same things by extending something else?
  • will this raise my codebase’s coupling too much?

Also, since this is basically a global variable on steroids it goes without saying that if you have a problem with global variables you should use anything but this (i.e.: if you want to perform unit testing). In general a lot of people have a lot to object to the use of singletons, so inform yourself and make it your call.

singleton unity3d inheritance

How to singleton

[Notice: this part was written differently due to a buggy behaviour that now I can’t reproduce]

Since this is a design pattern you will find a host of different implementations of it and they will all be just as correct as this is, the real question is which way is more suitable to you.

In unity for instance if you use the singleton as a component in a GameObject you can be pretty sure that you won’t need to bother with locks as they did in the unity wiki.

Also, I assume you aren’t trying to implement just one singleton class but that you’ll need a number of them and that you want to do it without duplicating code.

Well, its one kind of singleton inheritance, I guess...
Well, its one kind of singleton inheritance, I guess…

Given these assumptions here’s my implementation of it: we start with a generic class called SingletonBehaviour that inherits from MonoBehaviour, then whenever you want to create a singleton you just mark that class as inheriting SingletonBehaviour.

Let’s look at the code:

public class SingletonBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{

As I said this will be a generic class, that uses T as a parameter to indicate the actual type of the singleton we want to instantiate by inheritance. And that type will only be constrained to be a MonoBehaviour, so that only scripts that can be a component of a gameobject can be used for this.

    public static T instance;

This is where the references of our subclasses will be stored. Since it’s static only one instance per type is allowed.

Now let’s see what we do when an instance is created:

    public virtual void Awake()
    {
        if (instance != null)
        {
            Debug.LogError("Duplicate subclass of type " + typeof(T) + "! eliminating " + name + " while preserving " + instance.name);
            Destroy(gameObject);
        }
        else
        {
            instance = this as T;
        }
    }

The first thing to do is to check if this class has already been instantiated (notice, you can also use if(instance) if you don’t care for readability as you should), if that’s the case the GameObject is to be destroyed. Why the whole GameObject? Because this is a kind of failure so serious you want it to flash everything, add a Debug.Break() too if needed.

For this tutorial’s purpose I’ve also added a (quite verbose) error message. Otherwise, we set the current class’ instance in the instance variable.

    public virtual void OnDestroy()
    {
        if (instance == this)
            instance = null;
    }

That is, only if the instance being destroyed is the same one being stored we go on and clean the contents of the instance variable.

So, now to use this one only needs to inherit from this class like this:

public class SomeSingleton : SingletonBehaviour<SomeSingleton>

Notice that you are not enforced to use the same class as generic parameter by the compiler, which means that you could even have different classes compete for the same slot. I won’t recommend doing that on purpose: if you want to manage different singletons for one “slot” it’s best done explicitly instead of by relying on who gets there first.

That’s all folks!

Once again instead I’ve built for you a test project so that you can download and test it in action, but of course down here comes also the copy-pasteable version.

I hope you enjoyed this tutorial, and that you will consider joining my newsletter. Please also tell me what you think of this and if you think I should cover more design patterns, either here or by hitting me up on twitter.

P.S.: I’m currently looking for a job, give a look to my portfolio if you are interested.

using UnityEngine;

public class SingletonBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T instance;

    public virtual void Awake()
    {
        if (instance)
        {
            Debug.LogError("Duplicate subclass of type " + typeof(T) + "! eliminating " + name + " while preserving " + instance.name);
            Destroy(gameObject);
        }
        else
        {
            instance = this as T;
        }
    }

    public virtual void OnDestroy()
    {
        if (instance == this)
            instance = null;
    }
}
Share
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

2 thoughts on “The singleton post – making a Singleton in Unity3d with inheritance”

  1. The following would work:
    static T instance;

    There is no need for a dictionary, as the ‘instance’ variable is NOT shared.

    A static variable in a generic class declaration is shared among all instances of the same closed constructed type (§26.5.2), but is not shared among instances of different closed constructed types. These rules apply regardless of whether the type of the static variable involves any type parameters or not.

    http://www.ecma-international.org/publications/standards/Ecma-334.htm

    1. This is awkard… that was the first version I tested and it plainly didn’t work. The subclasses eliminated each other on the first try. Now I can’t reproduce this behaviour any more even by checking out the same commit from my repository that gave it before.
      Well, I guess I have no choice but to update the tutorial and look for drug traces in my tea cup.

Leave a Reply

Your email address will not be published.