34
\$\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\$
  • \$\begingroup\$ What is said GameManager supposed to do? Does it have to be a GameObject? \$\endgroup\$ – bummzack Feb 2 '16 at 14:27
  • 1
    \$\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\$ – CaptainRedmuff Feb 2 '16 at 15:01
  • \$\begingroup\$ this tutorials very nicely explained, how to implement singleton unitygeek.com/unity_c_singleton , I hope it is usefull \$\endgroup\$ – Rahul Lalit Aug 5 '16 at 13:18
26
\$\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\$
  • 2
    \$\begingroup\$ You might also want OnDestroy() { if (this == _instance) { _instance = null; } }, if you want to have a different instance in each scene. \$\endgroup\$ – Dietrich Epp Feb 3 '16 at 0:34
  • \$\begingroup\$ Instead of Destroy()ing the GameObject you should raise an error. \$\endgroup\$ – Doodlemeat Dec 9 '17 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\$ – PearsonArtPhoto Dec 9 '17 at 21:29
  • \$\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\$ – Michael Eric Oberlin Sep 4 '18 at 19:10
  • \$\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\$ – Jakub Arnold Apr 27 at 1:27
23
\$\begingroup\$

Here's a quick summary:

                 Create object   Removes scene   Global    Keep across
               if 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\$
  • 1
    \$\begingroup\$ Note: it should be possible to combine all three methods to create a 4th method that has all four features. \$\endgroup\$ – Draco18s Feb 2 '16 at 18:09
  • 3
    \$\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 '18 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\$ – Draco18s May 28 '18 at 16:34
16
\$\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!
\$\endgroup\$
  • \$\begingroup\$ This is pretty solid. Coming from a programming background and non-Unity background, can you explain why the singleton isn't managed in the constructor rather than in the Awake method? You can probably imagine that to any developer out there, seeing a Singleton enforced outside of a constructor is an eyebrow raiser... \$\endgroup\$ – netpoetica Apr 18 at 21:47
  • 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\$ – XenoRo Apr 19 at 0:35
  • \$\begingroup\$ I'm not sure I follow how to utilize this. Is this meant to simply be the parent of the class in question? After declaring SampleSingletonClass : Singleton, SampleSingletonClass.Instance comes back with SampleSingletonClass does not contain a definition for Instance. \$\endgroup\$ – Ben I. Aug 21 at 14:28
  • \$\begingroup\$ @BenI. You have to use the generic Singleton<> class. That is why the generic is a child of the base Singleton class. \$\endgroup\$ – XenoRo Aug 23 at 4:54
  • \$\begingroup\$ Oh, of course! It's quite obvious. I'm not sure why I didn't see that. =/ \$\endgroup\$ – Ben I. Aug 23 at 13:39
6
\$\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\$
  • \$\begingroup\$ That's very handy. I was just about to post a comment on @PearsonArtPhoto's response to ask this exact question :] \$\endgroup\$ – CaptainRedmuff Feb 2 '16 at 15:32
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\$
  • \$\begingroup\$ This is very nice! \$\endgroup\$ – CaptainRedmuff Feb 2 '16 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 '17 at 19:18
3
\$\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\$
  • \$\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\$ – Jakub Arnold Apr 27 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 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 at 9:57
2
\$\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\$
  • \$\begingroup\$ Please avoid link-only answers, by including in your answer at least a summary of the information you hope readers will glean from the link. That way if the link ever becomes unavailable, the answer remains useful. \$\endgroup\$ – DMGregory Jun 24 '18 at 18:15
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\$

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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.