c#

Singleton : Implementation in Unity3d C#

Unity_Singleton

Objective :

Singleton is a very complex topic, In this, we try to understand basics and various implementation of Singleton in Unity3d using C#.

Intro:

Singleton is a basic Design Pattern. Classes implementing Singleton pattern will ensure that only one instance of the object ever exists at any one time. It is recommend using Singletons for things that do not need to be copied multiple times during a game.This is great for controller classes like GameManager or AudioController.

Implementation:

There are several ways of implementing Singleton in Unity, we will some of the implementation in this tutorial

  1. Simplest Implementation

public class SingletonController : MonoBehaviour {
public static SingletonController instance;

  private void Awake() {
   if (instance != null) {
     Destroy(gameObject);
   }else{
     Instance = this;
   }
 }
}

Above code is the simplest implementation of Singleton, but there are some issues which we have to address

  1. Singleton is not persistent across the Unity scenes.
  2. All the executable code must be attached to GameObject in the hierarchy.
  3. It is not recommended to call SingletonController.Instance in any Awake() method because, since we don’t know the order that Awake() will be executed through all scripts, we can end up with a Null Reference Exception.
  4. This code works only for SingletonController Class, but if you want another singleton controller eg. AudioController, we have to copy paste the same code to AudioController Class and do some minor changes to works, but this leads to boilerplate code .

 

Solution For First Issue:

This one is easy to fix, just add the DontDestroyOnLoad(gameObject)


public class SingletonController : MonoBehaviour {
public static SingletonController instance;

  private void Awake() {
   if (instance != null) {
     Destroy(gameObject);
   }else{
     Instance = this;
     DontDestroyOnLoad(gameObject);
   }
 }
}

Solution for Second and Third Issue :

For this issue we have to create the Singleton at the time it is required, means we have to lazily instantiate the SingletonController in Unity


public class SingletonController : MonoBehaviour 
{
   

 private static SingletonController instance = null;
 
   
 public static SingletonController Instance
 
    {
 
      get
     
 {
         if(instance == null)

         {

            instance = FindObjectOfType<SimpleSingleton>();

            if( instance == null)
 
            {
             
 GameObject go = new GameObject();
              go.name = "SingletonController";
              instance = go.AddComponent<SingletonController>();
 
              DontDestroyOnLoad(go);
 
            }
         
 }
          

 return instance;

        }
     
 }
    


 void Awake()
 
     {

       if(instance == null )
 
       {
         instance = this;
 
         DontDestroyOnLoad(this.gameObject);
 
       }
      
 else
       {
         Destroy(gameObject);
 
       }
    }

}

Above code solves two different issues, it first searches for instance of SingletonController  in the scene, If it doesn’t find a SingletonController component, a GameObject is created and a SingletonController component is attached to it, so with this it is not necessary for SingletonController to exist in the scene before hand, and  this code will also destroy any additional copies it finds.

As in this implementation we are lazily instantiating the Singleton, so now we did not worry about Null Reference Exception.

Solution for Fourth Issue : Generic Unity Singleton

The fourth issue was boilerplate code, so we need generic implementation of Singleton to solve this issue

public class GenericSingletonClass<T> : MonoBehaviour where T : Component
{
    private static T instance;
    public static T Instance {
      get {
        if (instance == null) {
           instance = FindObjectOfType<T> ();
           if (instance == null) {
             GameObject obj = new GameObject ();
             obj.name = typeof(T).Name;
             instance = obj.AddComponent<T>();
           }
        }
       return instance;
      }
    }

    public virtual void Awake ()
    {
       if (instance == null) {
         instance = this as T;
         DontDestroyOnLoad (this.gameObject);
    } else {
      Destroy (gameObject);
    }
  }
}

So with this class we can make any class singleton, without duplicating  the code. Just inherit your class from GenericSingletonClass and it ready to go.

e.g

public class MyAudioController : GenericSingletonClass<MyAudioController>; 
{
 
}

 

Conclusion:

Singleton is bit complex, but it plays very important role in game development. In complex game we may need many Singleton, so it is good to have a generic implementation of Singleton to reduce code duplication. Fourth solution deals with most of the issue.

 

I am happy to hear from you guys, Please share your view in the comment section.

12 comments

  1. SaphireS

    Great article!

    (You wrote “Sigleton” in the very last code snippet btw)

    1. UG Post author

      I am glad, you find it helpful.
      Thanks for pointing typo

  2. rosdi

    Nice… I am copying the code… but I would have call that class SingletonMonoBehaviour instead of GenericSingletonClass… just my personal preference… makes the intent clearer I think.

  3. João

    Typo in the last snippet

    1. UG Post author

      Thanks, I updated the post

  4. Pingback: Delegates and Events in Unity - Unity Geek

  5. toby

    I inhered MySingletonClass from this class. There is an Awake() method in MySingletonClass. Do I need to override or new the Awake? Otherwise there is a warning :
    ” MySingletinClass.Awake()’ hides inherited member `Singleton.Awake()’. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword (CS0114) (Assembly-Sharp)”
    I test it and it runs well on new or override, but also it runs well if I don’t change anything and leave the warning there.

    1. UG Post author

      Just use Override keyword and just call base.Awake() from your MySingletonClass Awake()

      public override void Awake()
      {
      base.Awake();
      // here you can add other intialization code
      }

      but if you don’t use either “Override” or “new” keyword and don’t call base.Awake(), you will miss the important part of singleton that is persistence across the Unity scenes.

      1. toby

        Thank you! I have another question. The console show “DontDestroyOnLoad only work for root GameObjects or components on root GameObjects.”. Because my singleton was attach on a child gameobject. So how to solve this problem if my singleton is not on a root gameobject?

        1. UG Post author

          hi toby, this restriction from unity.If you don’t want your singleton to be persistent across the scene, just comment that part from the generic singleton class or you have to attach it to the root object.

  6. Mike

    I don’t like singletons, once you go strangeIoC way there is no turning back. Also that formatting makes my eyes bleed..

    1. UG Post author

      Thanks Mike for you suggestion, I will definitely try StrangeIoc. I am sorry for that,I think I should increase the font size

Leave a Reply

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