In Unity, how do I correctly implement the singleton pattern?

  • 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.

    What is said GameManager supposed to do? Does it have to be a GameObject?

    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.

    this tutorials very nicely explained, how to implement singleton http://www.unitygeek.com/unity_c_singleton/ , I hope it is usefull

  • 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.

    You might also want `OnDestroy() { if (this == _instance) { _instance = null; } }`, if you want to have a different instance in each scene.

    Instead of Destroy()ing the GameObject you should raise an error.

    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.

    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.

    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 https://wiki.unity3d.com/index.php/Singleton (which might be outdated though, but seems to work from my experimenting with it)

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM