Unity C#: Singleton

In this post of ours, we will be learning about how to use Singletons in Unity C#. If you are not aware of what a Singleton is? Read on, this will help you learn it. If you are aware of what a Singleton is, read on! Let us know if you know anything more about Singletons or even, let u know the mistake that we have committed. Comment below, share your post and what not.

OK! Now, what exactly is a Singleton?
First things first, it's a Class. Yes! Singleon is a Class which allows you to create a single instance of itself, and access to which will generally be granted.

What is the drawback that Singleton overcomes?
Say, I have a class named NormalClass and a function named SomeFunction as in the code below:

public class NormalClass: MonoBehaviour {

    public void SomeFunction(){
  //some code here
 }

}

To access SomeFunction from another Gameobject we would use:

FindObjectOfType<NormalClass>().SomeFunction();

We have this code which is kind of confusing and looks ugly. If you find that attractive and you find no problem in it, then maybe you have not considered the situation where in we do not have a NormalClass object, it will give you a NullReferenceException. To avoid this, we would probably need to do a null check

NormalClass normalClass = FindObjectOfType<NormalClass>();
if(normalClass!=null){
 normalClass.SomeFunction();
}

Now, the drawback is, we have to write all the above code all over again if we want to use it somewhere else. This is where Singletons come into picture.

Can you give us an example of how does a basic Singleton work?
Well, ya. Here you go:

public class SingletonClass: MonoBehaviour {

 //public static reference that can be accesd from anywhere
   public static SingletonClass Instance {
      get;
  private set;
   }

   //public property which can be accessed using the instance
   public string someString = "some value";

   void Awake(){
      //Save the current singleton instance
      Instance = this;
   }

   //public method accessed using the instance
   public void SomeFunction(){
  //some code here
 }

}

How do I use the above code?
The public properties i.e., the testString and SomeFunction, can be accesed using:

//set the someString variable
SingletonClass.Instance.someString = “The Game Contriver”;

//get the someString variable
string str = SingletonClass.Instance.someString;

Wait. How do I use it though. I mean, where do I attach it?
Attach it to any GameObject in a scene where you want this to be used.

Nice. But, I want something that is persisitent. I don't want to attach this script to a GameObject in every scene. How can thi be done?
DontDestroyOnLoad. This will help you achieve this. It makes the object persistent even on loading new scene and hence the script, which is attached to this object, persistent as well.

Cool. Can you modify the above code so as to incorporate this DontDestroyOnLoad?
Ah, that sounds greedy. But yeah, since I am responsible in making you that. I will have reap what I had sown. And, I will have to modify it for you.

public class SingletonClass: MonoBehaviour {

 //public static reference that can be accesd from anywhere
   public static SingletonClass Instance {
      get;
  private set;
   }

   //public property which can be accessed using the instance
   public string someString = "some value";

   void Awake()
   {
      //First we check if there are any other instances conflicting
      if (Instance != null && Instance != this)
      {
         //Destroy other instances if they are different
         Destroy(gameObject);
      }

      //Save the current singleton instance
      Instance = this;

  //make this object persistent
      DontDestroyOnLoad(gameObject);
   } 
   //public method accessed using the instance
   public void SomeFunction(){
  //some code here
 }

}


Now before you ask me how do I use this, I will make it clear, you got to add this in the first scene that you need this code to be in. To be on the safer side, add it to the first scene of your game so that there are no situations where in you would need to use this in the previous scene as this would be the available in the first scene of the game. And yes, you can use the same syntax to access the public properties.

Well, what about the NullReferecneException error? I don't think you have taken care of that. Have you?
Good point. Well, no. I haven't. Here's a better way:

using UnityEngine;
using System.Collections;

public class SingletonClass: MonoBehaviour {

 //private reference which can be accessed by this class only
 private static SingletonClass p_instance;
 //public static reference that can be accesd from anywhere
 public static SingletonClass Instance {
  get{
   //check if instance has not been set yet and set it it is not set already
   //This takes place only on the first time usage of this reference
   if(p_instance==null){
    p_instance = GameObject.FindObjectOfType<SingletonClass>();
    DontDestroyOnLoad(p_instance.gameObject);
   }
   return p_instance;
  }

 }
 
 //public property which can be accessed using the instance
 public string someString = "some value";
 
 void Awake()
 {
  if(p_instance == null)
  {
   //make the current instance as the singleton
   p_instance = this;
   //make it persistent  
   DontDestroyOnLoad(this);
  }
  else
  {
   //If more than one singleton exists in the scene
   //find the existing reference from the scene and destroy it
   if(this != p_instance)
    Destroy(this.gameObject);
  }

 } 
 //public method accessed using the instance
 public void SomeFunction(){
  //some code here
 }
 
}

Nice! Oh wait, isn't this the same as the static class?
Well, yes. To an extent it is the same as the Static classes. The major noticeable difference is obviously the syntax used in calling the properties. In Singleton, you use – SingletonClass.Instance.someFunction() whereas, in Static classes you would use – StaticClass.someFunction()
There are two more differences which I feel are worth mentioning - Static classes cannot be inherited nor do they implement an Interface.

These are some questions which I had when I was learning Singletons. Hope you found these useful. Any more questions on this are welcome as it only adds to our understanding of this peculiar topic, which is cursed most of the times. However, everything has it's place and this surely has one.

You can find a practical example of Singletons in the post of Add a Loading Scene in Unity, which we had written some time back.

See you around.
Share on Google+

About Sujit Horakeri

Sujit Horakeri is a game freak just like any other next door guy you would come across. He is a Web Developer by Profession, Game Developer by Choice.
Connect with him on:
    Blogger
    Facebook

1 comments:

  1. Another great article from a very great site.. Keep going :)

    ReplyDelete