The singleton pattern is one of the most famous patterns used widely in unity while developing games. We mostly see these being used with manager scripts like game managers, audio managers and UI managers.
So, in basic terms, a singleton is some object that gets generated only once throughout the game's lifecycle. An example would be a transition UI being made a singleton object on DontDestroy
which lets its instance get accessed by any other object easily.
Singleton Use Cases
For a classic way to create a singleton, we first take a static instance of the class we want to make a singleton of. A basic singleton would look something like this:
So in the code above, we first create a private static instance of the UIManager class itself and then, in the Awake()
function, we check if the instance is null. If the instance is null, we assign the current instance to the static instance.
So with this, any code can access it via: UIManager.instance.**
. However, a better and safer approach for a singleton creation would also look like this:
So, in the above code, we haven't done much change but created a getter property called GetInstance()
, which provides us with an instance of the current created instance and if we haven't created an instance yet, it will create a new instance and provide it to us.
We can access this by UIManager.GetInstance().**
. We have created a private constructor for this class to ensure that it isn't being instantiated from anywhere else in the codebase.
Creating and Using Generic Singleton
Now, I suggest you minimize the use of singletons as much as possible in your projects. But for this blog, I will show you how to create a script that can handle generic singletons of any type.
So, the above code is one of the most used scripts from my reusable utility toolkit while I am working on multiple projects. It solves the redundancy I would create while creating singletons for multiple classes.
Explanation
For example, if I had to create singletons of classes A, B and C, I would have to implement the logic to generate static instances in all these classes Awake()
or Start()
. The class above inherits this class for any of my MonoBehaviour-based scripts and passes in the class name as the type of singleton. It will automatically generate a singleton of that class and manage it for me.
In this code, we first create a generic class Singleton
that inherits from MonoBehaviour, which can be inherited by other classes. We also pass in T
for the type, where T
needs to be inheriting the MonoBehaviour class. Then, we create a static getter property with a Type T
instance, which returns us with an instance of our singleton.
To get our singleton instance, we check if the instance is null or not. If the instance is null, we assign our instance by searching for an object with the specified type. If the instance is already present, we destroy that certain type to ensure that we don't have multiple instances of our singleton.
After that, we ensure the object is set to DontDestroy
and goes through all our scenes without being destroyed.
Here's a usage example of the script:
So, doing this will create a singleton of type UIManager throughout the game that will only have its single instance throughout the game's lifetime. It can be accessed using UIManager.GetInstance()
from any code.
Conclusion
As you can see, using generic singletons can be very useful and make the code easier to edit and debug. You won't have to check through all the scripts to find their own instance. Even if you have to change your singleton, you can manage them through a single modular singleton class.
Thank you for reading and learning with me. Please subscribe and leave comments if you have any regarding this article.