Singleton Utility class I came up with. What do you think?

There are many ways to implement a singleton pattern. You can inherit from a base singleton class, or write out static accessors for each one if inheriting isn’t an option.

I’m working on a project that requires multiple singletons, but they all can’t inherit from a base class, so I wrote a utility class to make them quick and easy:

using UnityEngine;
using System.Collections.Generic;

namespace UnityExtensions {
   
    public static class Singleton {

        /// <summary>
        /// Holds cached references to multiple singletons.
        /// </summary>
        static Dictionary<string, MonoBehaviour> singletons = new Dictionary<string, MonoBehaviour>();

        /// <summary>
        /// Returns a cached reference if one exists, otherwise it finds and creates a cached reference. If no instance exists, throws an error.
        /// </summary>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        public static T Get<T>() where T : MonoBehaviour {

            var type = typeof(T).Name;
            T instance;

            if (singletons.ContainsKey(type) && (instance = singletons[type] as T))
                return instance;

            if (!(instance = GameObject.FindObjectOfType<T>()))
                throw new UnityException("No instance of "+type+" exists. Place one in the editor.");

            if (singletons.ContainsKey(type))
                singletons[type] = instance;
            else
                singletons.Add (type, instance);

            return instance;

        }

        /// <summary>
        /// Should be called in a singletons Awake() or Start(). Ensures only one instance of a singleton exists.
        /// </summary>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        public static void Ensure<T>() where T : MonoBehaviour {
           
            T instance = Get<T>();
           
            var instances = GameObject.FindObjectsOfType<T>();
           
            if (instances.Length != 1) {
               
                Debug.LogError ("Only one instance of "+(typeof(T)).Name+" should ever exist. Removing extraneous.");
               
                foreach(var otherInstance in instances)
                    if (otherInstance != instance)
                        Object.Destroy (otherInstance);

            }
        }

Usage is as follows:

public class Manager : MonoBehaviour {

    public static Manager instance {
       
        get {
            return Singleton.Get<Manager>();
        }
       
    }

    void Awake() {
        Singleton.Ensure<Manager>();
    }

}

Works well. Anything I didn’t think of?

1 Like

So I was considering adding the functionality of not having to inherit from ‘Singleton’ for my Singleton Utility.

This inspired me to add it.

Just updated my version here:

Primary thing that I wanted with my Singleton Util is the ability to decide what Singletons survive through load, and which are scene specific. This is useful if say you have like an audiomanager, or spawnpool, or whatever that’s a singleton, but is specific to a scene. Each scene gets their own singleton of them dropped in it and configured. That way you don’t bloat up memory with it (say the audiomanager contains references to all the background music for that scene).

Anyways, with mine if you wanted to implement ISingleton instead of directly inheriting from Singleton you’d just do the basic boiler plate:

public class SomeSingletonExample : SPComponent, ISingleton
{
    [SerializeField()]
    private Singleton.Maintainer _maintainer = new Singleton.Maintainer();

    #region ISingleton Interface

    public bool MaintainOnLoad
    {
        get { return _maintainer.MaintainOnLoad; }
        set { _maintainer.MaintainOnLoad = value; }
    }

    #endregion
   
    #region CONSTRUCTORS

    protected override void Awake()
    {
        base.Awake();
        _maintainer.OnAwake(this);
    }

    protected override void Start()
    {
        base.Start();
        _maintainer.OnStart();
    }

    protected override void OnDisable()
    {
        base.OnDisable();
        _maintainer.OnDisable();
    }

    protected override void OnEnable()
    {
        base.OnEnable();
        _maintainer.OnEnable();
    }
   
    #endregion

}
1 Like

Why not use Type directly as the key in your dictionary, instead of Type.Name? Also, I don’t like using “var” at all, but that’s just personal preference. Third, you should use Dictionary.TryGetValue(). Fourth, I don’t think it should be necessary to check a second time if the dictionary contains the key.

1 Like

Why are you converting the type into a string?

1 Like

Thanks for your notes and suggestions!

@blizzy I’d never heard of TryGetValue, good call.
And @Dantus I totally should have been using types as keys rather than strings. Brainfart.

As for your point, @lordofduct , i agree. Personally I don’t like the idea of giving singletons an interface simply because interfaces seem fundamentally at odds with the static nature of singletons, but I DO think I should add a default ability
for the singletons to not be destroyed on load, as you suggested. I came up with the Register method:

using UnityEngine;
using UnityExtensions;
using System.Collections;

public class Manager : MonoBehaviour {

    public static Manager instance {
        get {
            return Singleton.Get<Manager>();
        }
    }

    void Awake() {
        Singleton.Ensure<Manager> ();
    }

    //Since the static constructor is called before any instances are created or any static methods are called, it's a perfect place to 'Register'
    //a singleton. Register allows you to determine weather the singleton should be destroyed on load, and also defines a build method: If the singleton
    //hasn't been placed in the editor, but is refrenced by it's instance method, it'll attempt to use this method to create it. You could use this
    //to create a singleton that has a complicated prefab, for example, if you're testing a scene that it doesn't exist in to begin with.
    static Manager () {

        Singleton.Register<Manager> (
            dontDestroyOnLoad: true,
            buildFunction: ()=>{
                return new GameObject("Manager", typeof(Manager)).GetComponent<Manager>();
            }
        );

    }
   
}

Updated code with all your suggestions follows:

using UnityEngine;
using System;
using System.Collections.Generic;

namespace UnityExtensions {
   
    public static class Singleton {

        struct RegisteredSingleton {
           
            public Func<MonoBehaviour> buildFunction;
            public bool dontDestroyOnLoad;
           
        }

        static Dictionary<Type, RegisteredSingleton> registrations = new Dictionary<Type, RegisteredSingleton>();
        static Dictionary<Type, MonoBehaviour> singletons = new Dictionary<Type, MonoBehaviour>();

        /// <summary>
        /// Returns a cached instance if one exists, otherwise it finds and creates a cached reference. If no instance exists,
        /// it looks for a registration method to build the singleton. If it cant find a method, or that method doesn't succeed
        /// in constructing an instance, it throws an error.
        /// </summary>
        /// <typeparam name="T">Reference to singleton by type.</typeparam>
        public static T Get<T>() where T : MonoBehaviour {
           
            Type type = typeof(T);
            MonoBehaviour value;
            T instance;
           
            //If the instance exists in the dictionary and hasn't been destroyed, we return it.
            if (singletons.TryGetValue(type, out value) && (instance = value as T))
                return instance;
           
            //Otherwise we try to find it in the scene.
            else if (!(instance = GameObject.FindObjectOfType<T>())) {
               
                //If we can't find it, we try to see if it's been registered so we can run the build method to construct it.
                RegisteredSingleton registration;
                if (registrations.TryGetValue(type, out registration) && registration.buildFunction != null) {
                   
                    instance = registration.buildFunction() as T;
                   
                    if (!instance)
                        throw new UnityException("Singleton "+type.Name+" was registered with a build method, but it didn't return an instance!");
                   
                    else if (registration.dontDestroyOnLoad)
                        MonoBehaviour.DontDestroyOnLoad(instance);
                   
                } else
                    throw new UnityException("No instance of "+type.Name+" exists. Place one in the editor.");
               
            }
           
            singletons[type] = instance;
           
            return instance;
           
        }

        /// <summary>
        /// Should be called in a singletons Awake() or Start(). Ensures only one instance of a singleton exists. Additionally,
        /// if the singleton's been registered, it will apply DontDestroyOnLoad() as marked.
        /// </summary>
        /// <typeparam name="T">Reference to singleton by Type.</typeparam>
        public static void Ensure<T>() where T : MonoBehaviour {
           
            T instance = Get<T>();
            var type = typeof(T);

            RegisteredSingleton registration;
            if (registrations.TryGetValue(type, out registration) && registration.dontDestroyOnLoad)
                MonoBehaviour.DontDestroyOnLoad(instance);
           
            var instances = GameObject.FindObjectsOfType<T>();
            if (instances.Length != 1) {
               
                Debug.LogError ("Only one instance of "+type.Name+" should ever exist. Removing extraneous.");
               
                foreach(var otherInstance in instances)
                    if (otherInstance != instance)
                        MonoBehaviour.Destroy (otherInstance);
               
            }
        }

        /// <summary>
        /// Should be called in a singletons static constructor. If a build method is supplied that returns a singleton of the supplied type, it will use that
        /// method to create that singleton should one not exist when attempting to reference it's static instance variable. Additionally, a singleton can be
        /// registered so that DontDestroyOnLoad() is automatically applied.
        /// </summary>
        /// <typeparam name="T">Reference to singleton by Type.</typeparam>
        public static void Register<T>(Func<MonoBehaviour> buildFunction, bool dontDestroyOnLoad = false) where T : MonoBehaviour {
           
            var type = typeof(T);
           
            if (registrations.ContainsKey(type))
                throw new UnityException("Cannot register the same singleton twice.");
           
            var registration = new RegisteredSingleton {
                buildFunction = buildFunction,
                dontDestroyOnLoad = dontDestroyOnLoad
            };
           
            registrations[type] = registration;
           
        }
    }   
}

I like this way better (it kinda looks like this I don’t have the code in front of me).

public class Singleton<T> : MonoBehaviour{
static T instance;
public static T Instance {get {return instance ==null ? GameObject.Find... : instance}}

void Awake(){
if (instance != null){
Destroy(this)
return;}
instance = this;
}

He’s basically trying to set up a system that removes the necessity of copy pasting the same boiler plate around. It is instead reduced to a single function call, so this way maintaining the implementation of the actual enforcement of the singleton is in one place.

Or in the case of me, I add features to my singletons as a whole. Like the maintenance of them cross scenes.

@OP

Here’s the thing… singletons aren’t static. If you needed a static class, you’d use a static class. A singleton is by design an object, and that object is forced to only have a single instance. Objects have interfaces, so defining an interface contract for one to use isn’t that odd.

Now, interfaces being at odds with unity in general because they seemed to spend 4 versions of unity completely ignoring them and building out a component architecture that wouldn’t just ignore them, but actively combat them… that is definitely at odds with interfaces. Lol. Thankfully in unity5 they started to change their direction.

But yeah, having an interface to implement is on par with having a base class to inherit from… and we already proposed designs where Singletons inherit from a Singleton base class.

Oh OK I didn’t look at the code too much. He’s basically creating a Singleton Manager. What’s wrong with the standard ‘inherit from Singleton’? The maintenance would still all be done in 1 script. You’d just have to inherit from a Singleton class.

Theres nothing wrong with inheriting from a singleton class. I wanted a solution that doesnt require it.

Suppose, as is my case, i want a singleton class that inherits from another base class without, as @lordofduct said, copy and pasting the same code over and over.