79
\$\begingroup\$

I have seen several videos and tutorials for creating singleton objects in Unity, mainly for a GameManager, that appear to use different approaches to instantiating and validating a singleton.

Is there a correct, or rather, preferred approach to this?

The two main examples I have encountered are:

First

public class GameManager
{
    private static GameManager _instance;

    public static GameManager Instance
    {
        get
        {
            if(_instance == null)
            {
                _instance = GameObject.FindObjectOfType<GameManager>();
            }

            return _instance;
        }
    }

    void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }
}

Second

public class GameManager
{
    private static GameManager _instance;

    public static GameManager Instance
    {
        get
        {
            if(_instance == null)
            {
                instance = new GameObject("Game Manager");
                instance.AddComponent<GameManager>();
            }

            return _instance;
        }
    }

    void Awake()
    {
        _instance = this;
    }
}

The main difference I can see between the two is:

The first approach will attempt to navigate the game object stack to find an instance of the GameManager which even though this only happens (or should only happen) once seems like it could be very unoptimised as scenes grow in size during development.

Also, the first approach marks the object to not be deleted when the application changes scene, which ensures that the object is persisted between scenes. The second approach doesn't appear to adhere to this.

The second approach seems odd as in the case where the instance is null in the getter, it will create a new GameObject and assign a GameManger component to it. However, this cannot run without first having this GameManager component already attached to an object in the scene, so this is causing me some confusion.

Are there any other approaches that would be recommended, or a hybrid of the two above? There are plenty of videos and tutorials regarding singletons but they all differ so much it is hard to drawn any comparisons between the two and thus, a conclusion as to which one is the best/preferred approach.

\$\endgroup\$
4
  • \$\begingroup\$ What is said GameManager supposed to do? Does it have to be a GameObject? \$\endgroup\$
    – bummzack
    Feb 2, 2016 at 14:27
  • 2
    \$\begingroup\$ It's not really a question of what the GameManager should do, rather how to ensure there are only ever one instance of the object and the best way to enforce that. \$\endgroup\$
    – Zack Brown
    Feb 2, 2016 at 15:01
  • \$\begingroup\$ There is actually a pseudo official way to use Singleton in Unity. Here is the explanation, basically create a Singleton class and make your scripts inherit from that class. \$\endgroup\$
    – Alakanu
    May 5, 2016 at 15:11
  • \$\begingroup\$ this tutorials very nicely explained, how to implement singleton unitygeek.com/unity_c_singleton , I hope it is usefull \$\endgroup\$ Aug 5, 2016 at 13:18

10 Answers 10

69
\$\begingroup\$

It depends, but usually I use a third method. The problem with the methods that you used is that in the event that the object is included to begin with, it will not remove them from the tree, and they can still be created by instantiating too many calls, which could make things really confusing.

public class SomeClass : MonoBehaviour {
    private static SomeClass _instance;

    public static SomeClass Instance { get { return _instance; } }


    private void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Destroy(this.gameObject);
        } else {
            _instance = this;
        }
    }
}

The problem with both of your implementations is that they do not destroy an object that is created later. It could work, but one could throw a monkey wrench into the works that could result in a very difficult to debug error down the line. Make sure to check in Awake if there is an instance already, and if so, destroying the new instance.

\$\endgroup\$
8
  • 6
    \$\begingroup\$ You might also want OnDestroy() { if (this == _instance) { _instance = null; } }, if you want to have a different instance in each scene. \$\endgroup\$ Feb 3, 2016 at 0:34
  • 2
    \$\begingroup\$ Instead of Destroy()ing the GameObject you should raise an error. \$\endgroup\$
    – Doodlemeat
    Dec 9, 2017 at 13:47
  • 2
    \$\begingroup\$ Possibly. You might want to log it, but I don't think you should raise an error, unless you are trying to do something very specific. There are many instances I can imagine that raising an error would actually cause more problem then it would fix. \$\endgroup\$ Dec 9, 2017 at 21:29
  • 1
    \$\begingroup\$ You may want to note that MonoBehaviour is spelled with the British spelling by Unity ("MonoBehavior" won't compile--I do this all the time); otherwise, this is some decent code. \$\endgroup\$ Sep 4, 2018 at 19:10
  • 1
    \$\begingroup\$ I know I'm coming late, but just wanted to point out, that this answer's singleton does not survive an editor reload, because the static Instance property gets wiped.An example of one that does not can be found either in one of the answers below, or wiki.unity3d.com/index.php/Singleton (which might be outdated though, but seems to work from my experimenting with it) \$\endgroup\$ Apr 27, 2019 at 1:27
49
\$\begingroup\$

Here's a quick summary:

                 Create object if  Removes scene  Global    Keep across
                 not in scene?     duplicates?    access?   Scene loads?

Method 1            No                No            Yes        Yes

Method 2            Yes               No            Yes        No

PearsonArtPhoto     No                Yes           Yes        No
Method 3

So if all you care about is global access, all three get you what you need. Use of the Singleton pattern can be a bit ambiguous about whether we want lazy instantiation, enforced uniqueness, or global access so be sure to think carefully about why you're reaching for the singleton, and choose an implementation that gets those features right, rather than using a standard for all three when you only need one.

(eg. if my game will always have a GameManager, maybe I don't care about lazy instantiation - maybe it's only global access with guaranteed existence & uniqueness I care about - in which case a static class gets me exactly those features very concisely, with no scene loading considerations)

...but definitely don't use Method 1 as written. The Find can be skipped more easily with Method2/3's Awake() approach, and if we're keeping the manager across scenes then we very likely want duplicate-killing, in case we ever load between two scenes with a manager already in them.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Note: it should be possible to combine all three methods to create a 4th method that has all four features. \$\endgroup\$ Feb 2, 2016 at 18:09
  • 10
    \$\begingroup\$ The thrust of this answer isn't "you should look for a Singleton implementation that does it all" but rather "you should identify which features you actually want from this singleton, and choose an implementation that delivers those features - even if that implementation is not a singleton at all" \$\endgroup\$
    – DMGregory
    May 28, 2018 at 12:48
  • \$\begingroup\$ That's a good point DMGregory. Wasn't really my intent to suggest "smash it all together" but that "nothing about these features that prevents them from working together in a single class." i.e. "The thrust of this answer is NOT to suggest pick one." \$\endgroup\$ May 28, 2018 at 16:34
38
\$\begingroup\$

The best implementation of a generic Singleton pattern for Unity I know of is (of course) my own.

It can do everything, and it does so neatly and efficiently:

Create object        Removes scene        Global access?               Keep across
if not in scene?     duplicates?                                       Scene loads?

     Yes                  Yes                  Yes                     Yes (optional)

Other advantages:

  • It's thread-safe.
  • It avoids bugs related to acquiring (creating) singleton instances when the application is quitting by ensuring that singletons cannot be created after OnApplicationQuit(). (And it does so with a single global flag, instead of each singleton type having their own)
  • It uses Unity 2017's Mono Update (roughly equivalent to C# 6). (But it can easily be adapted for the ancient version)
  • It comes with some free candy!

And because sharing is caring, here it is:

public abstract class Singleton<T> : Singleton where T : MonoBehaviour
{
    #region  Fields
    [CanBeNull]
    private static T _instance;

    [NotNull]
    // ReSharper disable once StaticMemberInGenericType
    private static readonly object Lock = new object();

    [SerializeField]
    private bool _persistent = true;
    #endregion

    #region  Properties
    [NotNull]
    public static T Instance
    {
        get
        {
            if (Quitting)
            {
                Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] Instance will not be returned because the application is quitting.");
                // ReSharper disable once AssignNullToNotNullAttribute
                return null;
            }
            lock (Lock)
            {
                if (_instance != null)
                    return _instance;
                var instances = FindObjectsOfType<T>();
                var count = instances.Length;
                if (count > 0)
                {
                    if (count == 1)
                        return _instance = instances[0];
                    Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] There should never be more than one {nameof(Singleton)} of type {typeof(T)} in the scene, but {count} were found. The first instance found will be used, and all others will be destroyed.");
                    for (var i = 1; i < instances.Length; i++)
                        Destroy(instances[i]);
                    return _instance = instances[0];
                }

                Debug.Log($"[{nameof(Singleton)}<{typeof(T)}>] An instance is needed in the scene and no existing instances were found, so a new instance will be created.");
                return _instance = new GameObject($"({nameof(Singleton)}){typeof(T)}")
                           .AddComponent<T>();
            }
        }
    }
    #endregion

    #region  Methods
    private void Awake()
    {
        if (_persistent)
            DontDestroyOnLoad(gameObject);
        OnAwake();
    }

    protected virtual void OnAwake() { }
    #endregion
}

public abstract class Singleton : MonoBehaviour
{
    #region  Properties
    public static bool Quitting { get; private set; }
    #endregion

    #region  Methods
    private void OnApplicationQuit()
    {
        Quitting = true;
    }
    #endregion
}
//Free candy!

How to Use It

public class YourManager : Singleton<YourManager>
{
}

or

public class GameManager : Singleton<GameManager>
{
// Your game-specific variables
  protected override void OnAwake()
  {
    // If needed, put your code here e.g. init your vars.
  }
}

When you want to get the singleton object from other scripts, you will write:

YourManager.Instance.[Your Method or Variable]
GameManager.Instance.[Your Method or Variable]
\$\endgroup\$
18
  • 1
    \$\begingroup\$ @netpoetica Simple. Unity does not support constructors. That's why you don't see constructors being used in any class inheriting MonoBehaviour, and I believe any class used by Unity directly in general. \$\endgroup\$ Apr 19, 2019 at 0:35
  • 2
    \$\begingroup\$ @XenoRo FindObjectsOfType which is called inside Instance property will basically not work if called from a different thread than the main thread. It raises an ArgumentException: Find can only be called from the main thread exception. \$\endgroup\$ Dec 18, 2019 at 5:00
  • 4
    \$\begingroup\$ the Quitting static variable doesn't work with the new Enter Play Mode options of Unity. See here why: forum.unity.com/threads/configurable-enter-play-mode.768689 \$\endgroup\$
    – Stéphane
    Jan 30, 2020 at 14:43
  • 2
    \$\begingroup\$ In case this comes up for future readers: the CanBeNullAttribute is part of ReSharper, a Visual Studio extension that helps with code analysis, testing, and generally catching errors before they bite you, among other handy tricks to help you work efficiently. If you don't use ReSharper, you can skip those attributes when implementing your own version of this answer. \$\endgroup\$
    – DMGregory
    Apr 15, 2020 at 17:16
  • 1
    \$\begingroup\$ @GayanWeerakutti If I remember correctly, it's to allow/offer an overridable alternative to Awake, that will run it's code after the base Awake, while keeping the base method encapsulated and inaccessible, as modifying or overriding the base method might break the persistence code. \$\endgroup\$ Dec 25, 2020 at 6:44
11
\$\begingroup\$

I'd just like to add that it may be useful to call DontDestroyOnLoad if you want your singleton to persist across scenes.

public class Singleton : MonoBehaviour
{ 
    private static Singleton _instance;

    public static Singleton Instance 
    { 
        get { return _instance; } 
    } 

    private void Awake() 
    { 
        if (_instance != null && _instance != this) 
        { 
            Destroy(this.gameObject);
            return;
        }

        _instance = this;
        DontDestroyOnLoad(this.gameObject);
    } 
}
\$\endgroup\$
0
5
\$\begingroup\$

Another option might be to split the class into two parts: a regular static class for the Singleton component, and a MonoBehaviour that acts as a controller for the singleton instance. This way you have full control over the singleton's construction, and it will persist across scenes. This also lets you add controllers to any object that might need the singleton's data, instead of having to dig through the scene to find a particular component.

public class Singleton{
    private Singleton(){
        //Class initialization goes here.
    }

    public void someSingletonMethod(){
        //Some method that acts on the Singleton.
    }

    private static Singleton _instance;
    public static Singleton Instance 
    { 
        get { 
            if (_instance == null)
                _instance = new Singleton();
            return _instance; 
        }
    } 
}

public class SingletonController: MonoBehaviour{
   //Create a local reference so that the editor can read it.
   public Singleton instance;
   void Awake(){
       instance = Singleton.Instance;
   }
   //You can reference the singleton instance directly, but it might be better to just reflect its methods in the controller.
   public void someMethod(){
       instance.someSingletonMethod();
   }
} 
\$\endgroup\$
2
  • \$\begingroup\$ This is very nice! \$\endgroup\$
    – Zack Brown
    Feb 2, 2016 at 20:09
  • 1
    \$\begingroup\$ I am having trouble understanding this method, can you expand a little more on this subject. Thank you. \$\endgroup\$
    – hex
    Nov 20, 2017 at 19:18
4
\$\begingroup\$

Here is my implementation of a singleton abstract class below. Here is how it stacks up against the 4 criteria

             Create object   Removes scene   Global    Keep across
           if not in scene?   duplicates?    access?   Scene loads?

             No (but why         Yes           Yes        Yes
             should it?)

It has a couple of other advantages compared to some of the other methods here:

  • It doesn't use FindObjectsOfType which is a performance killer
  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.
  • It's thread safe

    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
    public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
    {
        #region  Variables
        protected static bool Quitting { get; private set; }
    
        private static readonly object Lock = new object();
        private static Dictionary<System.Type, Singleton<T>> _instances;
    
        public static T Instance
        {
            get
            {
                if (Quitting)
                {
                    return null;
                }
                lock (Lock)
                {
                    if (_instances == null)
                        _instances = new Dictionary<System.Type, Singleton<T>>();
    
                    if (_instances.ContainsKey(typeof(T)))
                        return (T)_instances[typeof(T)];
                    else
                        return null;
                }
            }
        }
    
        #endregion
    
        #region  Methods
        private void OnEnable()
        {
            if (!Quitting)
            {
                bool iAmSingleton = false;
    
                lock (Lock)
                {
                    if (_instances == null)
                        _instances = new Dictionary<System.Type, Singleton<T>>();
    
                    if (_instances.ContainsKey(this.GetType()))
                        Destroy(this.gameObject);
                    else
                    {
                        iAmSingleton = true;
    
                        _instances.Add(this.GetType(), this);
    
                        DontDestroyOnLoad(gameObject);
                    }
                }
    
                if(iAmSingleton)
                    OnEnableCallback();
            }
        }
    
        private void OnApplicationQuit()
        {
            Quitting = true;
    
            OnApplicationQuitCallback();
        }
    
        protected abstract void OnApplicationQuitCallback();
    
        protected abstract void OnEnableCallback();
        #endregion
    }
    
\$\endgroup\$
4
  • \$\begingroup\$ Might be a silly question, but why did you make the OnApplicationQuitCallback and OnEnableCallback as abstract instead of just empty virtual methods? At least in my case I don't have any quit/enable logic and having an empty override feels dirty. But I might be missing something. \$\endgroup\$ Apr 27, 2019 at 1:33
  • \$\begingroup\$ @JakubArnold I haven't looked at this in a while but at first glance it looks like you're right, would be better as virtual methods \$\endgroup\$
    – aBertrand
    Apr 29, 2019 at 9:49
  • \$\begingroup\$ @JakubArnold Actually I think I remember my thinking from back then: I wanted to make aware those who used this as a component that they could use OnApplicationQuitCallback and OnEnableCallback: having it as virtual methods kind of makes it less obvious. Maybe slightly weird a thinking but as far as I remember that was my rational. \$\endgroup\$
    – aBertrand
    Apr 29, 2019 at 9:57
  • \$\begingroup\$ I know this is old but I have a couple of questions.... Why use OnEnable rather than Awake? And why use a dictionary rather than just a single instance? It makes me think like there could be multiple instances \$\endgroup\$ Jan 6, 2020 at 3:59
2
\$\begingroup\$

I will trow my implementation too for future generations .

void Awake()
    {
        if (instance == null)
            instance = this;
        else if (instance != this)
            Destroy(gameObject.GetComponent(instance.GetType()));
        DontDestroyOnLoad(gameObject);
    }

For me this line Destroy(gameObject.GetComponent(instance.GetType())); is very important because once I had left a singleton script on another gameObject in a scene and the whole game object was being deleted. This will only Destroy the component if it already exists.

\$\endgroup\$
1
  • \$\begingroup\$ wouldn't 'instance' be pointing to a destroyed object with this approach? \$\endgroup\$ Apr 2, 2020 at 15:59
1
\$\begingroup\$

I wrote a singleton class that makes easy to create singleton objects. Its is a MonoBehaviour script, so you can use the Coroutines. Its based on this Unity Wiki article, and I will add option to create it from Prefab later.

So you don't need to write the Singleton codes. Just download this Singleton.cs Base Class, add it to your project, and create your singleton extending it:

public class MySingleton : Singleton<MySingleton> {
  protected MySingleton () {} // Protect the constructor!

  public string globalVar;

  void Awake () {
      Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID());
  }
}

Now your MySingleton class is a singleton, and you can call it by Instance:

MySingleton.Instance.globalVar = "A";
Debug.Log ("globalVar: " + MySingleton.Instance.globalVar);

Here is a complete tutorial: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/

\$\endgroup\$
1
\$\begingroup\$

Alright, and here's my Singleton, which has the additional advantage of initializing lazily and detecting infinite initialization loops.

If you want it to not destroy on load you should set this up in your inheriting class. It will use FindObjectOfType if necessary, as sometimes you may want to access this from another object's Awake method.

using UnityEngine;
using System;

namespace Feed {
  public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T> {
    static T s_instance;
    static bool s_isInitializing = false;

    protected abstract void Initialize();

    public static bool TryGetInstance(out T instance) {
      if (s_isInitializing) {
        throw new InvalidOperationException(
          "Singleton initialization dependency cycle detected"
        );
      }
      if (s_instance == null) {
        var found = FindObjectOfType<T>();
        if (found == null) {
          instance = null;
          return false;
        }
        InitializeAndAssign(found);
      }
      instance = s_instance;
      return true;
    }

    public static T Instance {
      get {
        if (TryGetInstance(out var instance)) {
          return instance;
        }
        throw new InvalidOperationException($"Could not find instance of {typeof(T).Name} in scene");
      }
    }

    void Awake() {
      if (s_instance == null) {
        InitializeAndAssign((T) this);
      } else if (s_instance != this) {
        throw new InvalidOperationException(
          $"Tried to create two instances of singleton {typeof(T).Name}"
        );
      }
    }

    protected virtual void OnDestroy() {
      s_instance = null;
    }

    static void InitializeAndAssign(T instance) {
      if (s_instance != null) {
        throw new InvalidOperationException("Singleton already exists");
      }
      s_isInitializing = true;
      instance.Initialize();
      s_isInitializing = false;
      s_instance = instance;
    }
  }
}
\$\endgroup\$
0
\$\begingroup\$

https://github.com/jpgordon00/UnitySingleton

All you have to do is add 'SceneSingletonListener' to your scene and you can create singletons like so: using UnityEngine;

public class SingletonComp : Singleton { }

// in any class during runtime... SingletonComp = SingletonComp.Instance;

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Your code is missing a license and is hence unusable. \$\endgroup\$
    – user35344
    Oct 2, 2021 at 12:08
  • \$\begingroup\$ There is now a license, but that license is the GNU GPL, which makes it pretty much useless for any game you intend to sell. \$\endgroup\$
    – Philipp
    Oct 19, 2021 at 8:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .