BlogFeature

Why You Should Start Using Singletons in Unity

You have probably heard that you should use design patterns when developing games or any kind of software. However, some of us are stubborn enough to think that we do not need them. Well, if you think that way, you are wrong. I used to think that if I write organized code I would not need design patterns. One day, I reached a point in a project where I realized I was wasting development time and effort trying to find errors that could be avoided by using design patterns. Being organized was not enough. Let me tell you how I started using the Singleton pattern.

If you are not familiar with design patterns, it is ok, you do not need to know about them to laugh with this story. First, let me tell you that, Singleton, the simplest design pattern, consists in the creation of a class that can be instantiated only once.

Now that we know what Singleton is, let’s go back to my story. I used to think that having a script that was not destroyed on load could replace a Singleton. Therefore, in my main scripts, the ones that control the logic of my game, data, sound, and Input/Output I had the following line of code:

DontDestroyOnLoad(gameObject);

This way, they would be persistent through the whole game. The first problem that I found with this solution was that it made it really annoying every time I wanted to access these scripts, which was very often. I remember that I had to find the object and then get the script component that I wanted (very inefficient implementation). Another solution that I used was to have references to the main scripts in some of the other scripts that interacted with them more frequently. Yes, I know. This was an extremely bad replacement for a Singleton. One day, I was looking at my code and I saw the high number of references that I had to those main scripts. The code did not look organized and was not efficient. I could not keep adding changes to my project because the base of it was bad. It would cause more problems in the future to deal with my solution than to refactor my code. Well, I was wrong, I look at myself in the mirror, accepted my mistake and decided to start using Singleton from that moment on. I refactored all the scripts that needed to be singleton and persistent to add the following code:

public class SceneManager: MonoBehaviour
{
    void Awake()
    {
       Instance = this;
       DontDestroyOnLoad(gameObject);
    }

    public static SceneManager Instance{ get; private set; }
}

For instance, this is how I access my SceneManager class after implementing the Singleton pattern in it:

SceneManager.Instance

I felt great because I did not have to search for my class anymore, nor add extra references in other scripts. In addition, I was using design patterns in my project like good programmers do. Well, not quite. Unfortunately for me, the previous implementation was incomplete.

One day, yes, another day, I was testing a scene in my project. To make testing faster, I added a prefab of a game object that contained the main scripts, which loaded all the data needed in the game. As you can imagine, I forgot to remove that game object after testing. Which I discover after 1 hour of debugging. I mentioned my problem to a friend and he told me that my Singleton implementation should have handled that problem in the Awake method. Singleton checks whether the class was instantiated or not to destroy the second game object that was trying to create the new instance. I was like: “Ok, I do not check any of that.” My implementation was wrong, again. However, this last time, I checked on the internet and asked my friend to give a look at my code before I keep making changes. I finally had a good implementation of a Singleton.

public class SceneManager: MonoBehaviour
{
    void Awake()
    {
        if(Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public static SceneManager Instance{ get; private set; }
}

Now, I can access my scripts easily and ensure that only one instance of a class will be created. I hope you have learned with this story that you should not reinvent the wheel. If there is a solution already, and it is good, use it. Be critical with your code and if you can tell someone else to review it. Both of you can learn from a code review. If you had problems in your code, just like I had, do not think you are a bad programmer. Making mistakes is good, we grow when we learn from them. Remember that programming is a discipline that is improved through iterations.

Take a second to support The Debug Log on Patreon!
Previous post

Episode 20: Game Dev Resolutions

Next post

Episode 21: Game Monetization with Oscar Clark, Unity Evangelist

13 Comments

  1. Sylafrs
    February 18, 2016 at 8:17 am — Reply

    On Unity, be careful with “SceneManager” :p
    Even thought it’s on another namespace, the class that opens/closes scenes is now named like that :p

    • February 18, 2016 at 12:53 pm — Reply

      Thanks, SYLAFRS. I just learned something new today. I have not had problems so far because I use my own namespace in my projects. I will add it to the code in the document next time.

  2. dotmos
    February 18, 2016 at 12:45 pm — Reply

    To make this even more simple to use, don’t create the object in the editor, but let it instantiate itself.

    static SceneManager _Instance;
    public static SceneManager Instance{
    get {
    if(_Instance == null)
    {
    GameObject _go = GameObject.Instantiate(yourObject); //Load from resources folder and instantiate
    DontDestroyOnLoad(_go);
    _Instance = _go.GetComponent;
    }
    return _Instance;
    }
    }

    Before i started using uFrame MVVM, this was the way to go to easily implement services/databases. 😉

    • February 18, 2016 at 12:46 pm — Reply

      Oops,
      _Instance = _go.GetComponent;
      should be
      _Instance = _go.GetComponent();

    • February 18, 2016 at 12:55 pm — Reply

      Thank you very much, DOTMOS. I always appreciate new ways to implement a solution.

  3. February 19, 2016 at 8:33 pm — Reply

    From over 5 years ago, good breakdown of options to use. I personally always use #4 with the FindObject check before I determine I need to make a new GO.

    http://rockonflash.wordpress.com/2010/10/21/singletons-in-unity3d/

  4. February 24, 2016 at 8:12 pm — Reply

    it seems that there is a lot of discussions about the singleton pattern relevance depending on the situation. The main issue appears to be that it leads to hiding the dependencies of your implementation in the code, rather than making it clear in the functions signatures. Here is an example describing a few cons, but you can find many others : http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx

    • February 25, 2016 at 12:55 pm — Reply

      Thanks for your comment Cyprien. You are right, this is a controversial topic. We want to do another article explaining the cons of using Singletons so, thank you for the link. We really appreciate your help. Have an amazing day.

  5. Adrian Anta
    February 24, 2016 at 10:57 pm — Reply

    I don’t recommend using the Singleton pattern when you work in a team, as it’s the source of all kinds of code coupling. Use static variables instead if you have to assure that there is only one instance of the class.

    Nice work, keep it up!

  6. Clint Zirker
    February 25, 2016 at 3:49 pm — Reply

    What are your thoughts on IOC containers for Unity. I wrote a simple one and now my code looks like this…

    [GameService(Type = typeof(IEventSystem))]
    class EventSystemDelegates : IEventSystem {}

    [GameService(Type = typeof(ISceneManager)]
    class SceneManager : ISceneManager{}

    class SomeScript
    {
    [Autowired]
    IEventSystem eventSystem;

    [Autowired]
    ISceneManager sceneManager;

    void Start()
    {
    this.Autowire();
    sceneManager.DoSomeWork();
    eventSystem.RaisEvent(new SomeGameEvent());
    }
    }

  7. Alf
    February 25, 2016 at 11:34 pm — Reply

    @ADRIAN
    You r right .. team scale .. lifetime and purpose of steady game services are things to consider early to pick up the proper design patern .. the evil in singleton is how it s easy to hook up with them and bind massively things not supposed to stay there .. ???

  8. August 1, 2016 at 4:32 pm — Reply

    Did you prefer using a singleton to using a toolbox?

Leave a reply

Your email address will not be published. Required fields are marked *