It’s time to cover a topic that
I’ve been avoiding for a long time. And that’s the Singleton pattern. But first, I’m gonna need some coffee. Did I say coffee? I totally meant a beer, and I’m gonna need
it. Alright, let’s do this. The Singleton Pattern. The Singleton Pattern is a design pattern
that describes a class that is both globally accessible and can only be instantiated once. A classic example is the audio manager because,
generally speaking, it’s something you’ll need to access in a lot of scripts and that
you’ll want to make sure only exists once in any given scene. That doesn’t sound too bad, right? So why have I been avoiding Singletons for
so long? Well, if you’re listening carefully, you
may have picked up on something that makes the Singleton Pattern different from other
design patterns — that it has two technical requirements. One, a singleton must be restricted to a single
instance and two, it must also be globally accessible. Now, that might not seem like a big deal at
first. But together these two requirements offer
a tempting upfront value that is vastly outweighed by the pain they can cause in the long run. Let’s explore why by taking a look at each
requirement on it’s own. Imagine a simple project with a Player, Game
Manager, and some classes to handle basic tasks, like displaying health on the UI. In this example, the Game Manager is responsible
for ending the game when the player dies, so it has a reference to the Player class. But how does it get access to the Player in
the scene? Now, there’s actually a few ways to answer
that question, and I have a video that covers each one. But, for the sake of this video, just know
that we can either give the Game Manager a reference to the Player by setting an exposed
property from another script or the editor, or we can have the Game Manager retrieve a
reference to the Player for itself using, you guessed it, a Singleton which is globally
accessible. The choice seems obvious, right? Why would I bother constructing some fancy
way to pass the Player around my code when I could just turn it into a Singleton and
get access for free? What could possibly go wrong? Well, as it turns out, quite a bit — just
not at first. The Singleton Pattern solves a very big unknown
in Unity, which is how do you access other scripts? Or, another way to look at it is how do you
fill your class dependencies? Our Game Manager class depends on having a
reference to the Player, which is obvious because the Player class is part of its member
variables. Now, the effect I’m about to show you would
be more dramatic in a real world scenario where our Game Manager is a few hundred lines
long, but if we remove this member variable and access the Player singleton instance directly,
we effectively hide the fact that the Game Manager depends on having access to the Player,
which can lead to all sorts of problems down the road. Because you may know what your code is doing
the day you wrote it, but I promise you won’t remember when you try to refactor it a week
later. Or worse, try to explain it to someone else
who’s contributing to your project. Hiding your class’ dependencies just makes
everyone's lives more difficult in the long run. Now, admittedly, the pain of this might not
seem obvious at first. But when you consider that a Singleton can
be accessed from anywhere, it isn’t hard to conceive that you might actually start
referencing them more and more throughout your code — because, let’s be honest,
it’s just so easy. And with all those hidden dependencies comes
a layer of complexity that should be avoided as much as possible. But that isn’t the only issue. Here are two examples of our Player singleton
being used in the previous project. We’ve got a health bar and some logic to
save the game. Both access the player’s health, which is
nice and consistent. But what happens if we need to change how
health works — say we want to add a special type of Player that factors armor into its
overall fortitude. Well, any change we make to our singleton
will affect the entire game because the Player class is being referenced directly via the
Singleton Instance variable. However, if we refactor these classes and
make the Player class a dependency, we can fill that dependency with any class that derives
from Player, such as a class called ArmoredPlayer that implements the previously described functionality. Again, these pain points are subtle but their
effects snowball as your project grows. What seems easy to change here in these discrete
examples is much harder to do in a real world scenario. So much so, that you may find yourself exploring
the Ballmer Peak to make it through your day. Now, we’ve been talking about how using
Singletons can be harmful to a project, but their implementation, specifically in Unity,
can be harmful, as well. The other technical requirement of a Singleton
is that it must be restricted to a single instance. To accomplish this restriction you’d normally
hide your Singleton’s constructor by making it private and then lazily instantiating a
single Instance from the getter. But this typically doesn’t work in Unity
because most of your classes will probably derive from MonoBehaviour. And MonoBehaviours hide the constructor and
allow anyone to instantiate them via Object dot Instantiate. So how do you restrict MonoBehaviours to a
single instance? Well, you can do it but, unfortunately, it
requires some finagling to get it to work. The concept is the same in that if the Singleton
MonoBehavior doesn’t have a reference to an instance yet, it’ll go ahead and create
one of its own. But, first it has to check the scene to confirm
that one hasn’t already been created. That’s because there are a couple ways that
yourself or another developer can circumvent the single instance restriction — by adding
one or more instances directly into the scene from the editor, or by calling Object dot
Instantiate, like I mentioned before. So, the getter will need to check the scene
and grab the first instance it finds. Notice I said, “the first instance”. Because you could actually have multiple Singletons
in your scene. So MonoBehaviour based Singletons must destroy
themselves if another one exists when they’re created. Which adds a bit of magic that can lead to
some unexpected behavior. For example, if your Singleton makes a call
to DontDestoryOnLoad in order to persist through scene changes, there’s a chance that there’ll
be an instance of that Singleton in the new scene. And, what can happen is that, depending on
the order they’re arranged in the hierarchy, the wrong one could be deleted. So, it works but it isn’t the best solution. Now, where does that leave us? Am I saying to never use Singletons again? Well, let me put it this way. I and many other developers get by just fine
without them. I could get into more detail about how using
Singletons informs how you architect your entire project and creates bad habits that
cause you to tightly couple your code which effectively destroys its flexibility in the
long run. But instead, let me leave you with some criteria
to follow the next time you want to use a Singleton. One: does having more than one instance of
your potential Singleton fundamentally break your game? I mean, would your code literally throw an
exception and crash if you had more than of them in a single scene? Two: does it absolutely need to be accessed
by different parts of your code? And I’m not just talking about something
like a player class that might get referenced in the UI and the game manager, but does your
potential singleton need to be accessible by every nook and cranny of your code base? And finally, three: will your singleton control
concurrent access to a shared resource? Think of a data manager that has the ability
to open and close a save file, where simultaneous access to the file would actually throw an
exception. If you keep those three criteria in mind,
then you should have no trouble implementing Singletons that actually provide long term
value to your project. Otherwise, I strongly suggest learning the
techniques that you can use in Unity to safely pass data around your game code. And you can start with my video called “How
to Access Variables From Another Script in Unity”. Pretty on those nose, right? Give that a watch and let me know what you
think in the comments. Now, I know there are some pretty die hard
Singleton users out there. So if you think I missed the mark, let me
have it. Or if you agree with this video, then I’d
love some positive feedback as well. Welp, as always, thanks for watching and I’ll
catch you in the next video. Cheers.