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.