Truth about Singletons in Unity | New GameDevs WATCH!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today we're going to talk about one of the most heated topics in software development and game development it's something that comes up all the time and it's singletons some people think hey they're okay they're great other people think this is the worst thing that's ever happened you should never be using them and some people are kind of in between so today i want to talk about what singletons are why you should or should not use them how i maybe use them and i want to talk a lot about why they're hated and what the arguments against them are as well now if you don't know what singletons are make sure that you watch this through the end you're going to get some really invaluable information and if you do know what singletons are and you have some thoughts about them drop a comment down below before we get started i'm curious to see where you are at the beginning and if that changes at the end of the video let's start with the definition of a singleton and you don't want to just search for singleton definition on google you'll find some results that are interesting but not exactly what we want we want the singleton pattern and the singleton pattern in software engineering is a software design pattern that restricts the instantiation of a class to a single instance this is useful when exactly one object is needed to coordinate actions across the system and it says here that the term actually comes from that mathematical concept and the other definition that we found now if we scroll down a little bit more we can see that it says here the singleton design pattern is one of the 23 well-known gang of four design patterns from the old design patterns book that describe how to solve recurring design problems to design flexible and reusable object oriented software with the aim of making it easier to implement change tests and reuse objects so it's essentially a pattern that's described from way back then and it was of course used i think quite a while before then too and that's kind of how they came to describe it so why why is this pattern so big why does it come up so often and uh why is there a big giant section on criticism and why does it say that it's sometimes considered to be an anti-pattern that's what we're gonna get into today but before we move on this video is sponsored by sirenix they're the creators of my favorite unity tool which i've already talked about many times before and used for almost every project the odin inspector the inspector is a powerful user-friendly editor extension which helps speed up my workflow and now i'm excited that sirenix just released their new odin validator which includes a ton of new features and improvements the validator now lets you do real-time validation while working on your project which means you'll get notified as soon as an issue appears in your project you can now easily configure custom rules and they've even added three additional built-in attributes to help boost productivity the validator has been rebuilt from scratch to be better and faster with a more intuitive and user-friendly console go check out cerinix and their amazing tools by clicking the link in the description let's start by taking a quick look at a singleton in c sharp and then we'll dive into what a singleton looks like in unity talk about why they're different and go on to all of the other stuff that i've got to say about it and there's really a lot to say so a c sharp singleton is really a class that has a static reference to an instance of itself here you can see that they use the class name singleton which in my opinion kind of makes it confusing this could be any class name this could be player audio manager game manager random thing the class name doesn't necessarily matter it just has to match here so what they do is they create a class and then create a static instance of that class you usually name it something like instance or singleton you probably wouldn't want to have a class with a singleton named singleton personally i don't prefer prefer the name singleton for an actual class in my examples but that's what they've got here and then you can see the way that it works is there's a constructor that does absolutely nothing and then there's a public get property or public get only property that returns back a singleton this is static so you can call singleton dot instance from anywhere in your code and get a reference to it if it exists it will return back the instance right here on whatever line this is and if not it will create a new instance of it and then return that back out so it's essentially going to create one of these objects this example doesn't really help a lot because it doesn't do anything the singleton here doesn't actually do anything so it can be a little bit confusing in my opinion let's look at the unity version though because the unity version is slightly different and when you start searching for singletons you're going to find a lot of stuff about non-unity singletons and then you'll find the unity ones and see that there's this major difference and that's that when we create the singletons it's usually done in the awake method we don't have a constructor method and we very rarely do it in a lazy method like this uh get where you instantiate or create an object and that's because you can't new up a game object and have a reference to it right away if we try to do something like that down here and say that in the instance we want to get the instance of the object or create a new one well we would instantiate a new game object but that object wouldn't be ready until the next frame so we couldn't really return it back in a usable state so instead we do this little hack where in the awake method we just set the instance to our self so we have an object already in the scene and then when it spawns the reference is set automatically and if somehow we end up with two of the objects in our scene or active at a time this will actually destroy the second one this singleton doesn't have any methods or anything that we can do though so it's not very useful let's take a look at something slightly more practical here i've got a ship action text which is just a script that's going on to a single text object sitting out in my canvas that i want to be able to pop up and show some stuff on randomly throughout my game in this example we get the instance in awake but just by setting the instance to this you can see the instance is on line eight it's a static instance of this exact object or ship action text named instance with a getter and a private setter it's got public accessibly getter and a private setter so that it can only be set inside our own class the awake method sets the instance to it i don't go through the trouble of checking to see if the instance already exists and destroying the object because i know that in my game that's just not a scenario that i'm going to need to deal with and by the time that i get around to a scenario where i'm bouncing around different scenes and things i may completely refactor that and that's an important thing to remember when it comes to these singletons this is a singleton right now it makes it extremely easy for me to set the text of this object here as long as i've got a single thing that i want to set the text on if i start doing a whole bunch of these though then this becomes a mess because i can't have multiple ship action texts in that case i would start to consider doing some refactoring and changing away from singletons now in this case this text is really just for me to debug stuff and it's kind of sitting up on the screen for a little while and i know i'll end up deleting it or refactoring it into something like a ui manager which is another really common use for a singleton and i want to talk really quickly about a few common uses for singletons the most common things that you're going to find them for are well little hacks like this where you just want a quick reference to something you want to be able to get at something and you know that you'll probably just change that away or maybe it's just never going to matter you have this ship action text up there and you'll leave it there forever but most likely just kind of throw it away but as a quick easy way to reference something another common use though is things like the input manager in fact you see that a lot of the built-in systems in unity are essentially singletons but they're static classes that kind of work the same as singletons in fact that's kind of the core of a singleton is the use of a static reference to the object or a static instance of the object so some other uses let's see game managers input managers players players very often become a singleton and start off as a singleton and sometimes you'll want to convert your player to not be a singleton anymore maybe you've got a player character that you've got set up and then you decide oh we need multiple player characters one of the nice things about the singleton pattern at least in my experience is that usually it's very easy to refactor away from you can search for all of the references to the instance in fact one of the things i like to do is just go find the first line here or find the line where i reference the instance add in a little comment there and then try to do a build it's going to instantly give me all of the places that are referencing that instance and let me know about where i would need to switch away from searching for it from an instance to injecting it in which is kind of the refactoring alternative when you find that you've got too many singletons or you've got singletons that are problematic that you want to get rid of what you usually want to do is make it so that you can pass in the object or inject the dependency into the thing that needs it so my ship action text would probably actually just be passed into a ui manager that would then maybe have its own singleton or maybe the ui manager doesn't even need a singleton and it's just registering for whenever a ship action happens and it knows to pass over the event to send the text over to the ship action text without needing a singleton at all that's definitely a very viable way to convert this but i like to again start it off simple and then build from there so let's talk about why singletons are hated now what's the big problem why is it that everybody says oh you should never use singletons or i try to avoid them and there are a couple key arguments in fact let's pull them up on the wikipedia article real quick all right here it is the criticism so it says critics consider the singleton to be an anti-pattern which of course sounds terrible and it says it sound as it introduces global state into an application often unnecessarily and i think this is going to be the point of contention this in turn can place restrictions on any abstraction that uses the singleton per for example preventing concurrent use of multiple instances not really relevant here furthermore because it often exposes a globally visible accessor which is the public static instance that's what they're talking about that globally visible accessor its presence complicates dependency analysis by introducing a potential dependency on the singleton in all code it's visible to saying essentially that because it can be used by anything anywhere everything needs to know if it depends on it and things can start to depend on it it also says that singletons violate the single responsibility principle because they're responsible for making sure there's only one of them although you'll see that in most of my examples i just ignore that fact and assume that there's always only one of them and that it doesn't matter and then you see that the other one is that they are difficult to test because they make writing loosely coupled code quite a bit harder because your dependencies are no longer injected like the alternative they're not the ones that are passed in so that you can swap them out but they're a single dependency that you have to be able to get out all the time so let's hit these all in a row the first one global state global state is something that you're almost always going to have in a video game you think about it in a game you've got a player almost everything in the game needs to know about the player or needs to have some info about the player or is going to interact with the players in some way if the things aren't interacting with the player in some way they're probably not part of the game or they're like some sub part of an npc but generally everything in your game is interacting with the player and having global a globally accessible version of that that's easy to get at can come in really handy being able to say player.transform.position or player.instance.transform.position or whatever it is that you want to figure out where the player is makes it dramatically easier than having to figure out well how do i get a reference to this player or do i have to pass this in and do i have to add in a dependency there it's just quite a bit simpler to set up the code and to write the code you end up writing a lot less code and it's just fast because you're getting a direct static reference to that object you're not doing any extra work to get to that object you're just literally dereferencing that property there now of course you can get that same speed boost from injecting that reference right if you inject in the player then you're going to get the same direct reference to it but you do need to kind of figure out how you want to inject that so again i like to start with a singleton and then slowly morph things away and start binding up objects passing in references as the kind of architecture starts to come together but i always almost always start with the singleton that's globally accessible so i can figure out where those connections are going to be and then decide later if i need to clean that up now let's go on to the next part here which says that it prevents concurrent use of multiple instances and in most of the cases for our game dev stuff if we're making something a singleton that's exactly what we want we only want one instance of it we only want one in our game our game might be a single player game it only has one thing it might have a single enemy it only has that one reference to the enemy we don't want more or whatever the thing is it's got to be something that we only want one of otherwise it doesn't make sense to have it be a singleton but if it if there's only one of them then it's a great use for that so let's continue on it says that um it's not following the single responsibility principle in this case i just don't care to be honest like the the extra tiny bit that it's doing isn't worth worth even talking about in my opinion the single responsibility principle is a great principle it's great to follow and kind of let it guide you but it's not something that you should enforce and strictly make your code way more complicated just to follow or abide by in my opinion and then the final section back here was about being difficult to test and largely because that it's hard to swap things out when you have a singleton you're not injecting independencies so it's hard to pass in mock dependencies or mock versions of things that you can fake in your tests to make the tests easily work without depending on the actual object so instead of requiring an actual player in your unit tests you might want like a a mock player that doesn't work exactly like a player but you know just sends in commands to the enemy while you're testing the enemy or something like that it gets very more difficult to do when you have singletons that said it's not impossible to do when you have singletons you can definitely do it and in the unity case it's not very difficult at all because you can set up your play mode tests to just use prefabs that have these mock versions of them but in my experience the other thing is that most of the people aren't doing a whole lot of unit testing in game development and they're when they are doing the unit testing in game development they're rarely running into problems where they need to mock things out and they can't usually they want to test with the actual objects i'm sure there are some scenarios where this is a big issue for people but for the majority of people this is not a problem at all and singleton's really just have a lot of the benefits with few of the drawbacks so if you've been looking at ways to remove singletons from your project just because you think that they're terrible you've heard bad things about them my recommendation is to do it when it makes sense when you actually need multiple references to the thing or when the singleton is actually causing you some issues don't do it right away just do it as the project kind of grows and the architecture adjusts if you find that you have tons and tons of singletons then you should probably start looking at how to start data binding and how to pass in references to objects it's really not very complicated usually just make a method called bind pass in the objects that i want it to know about and then call it pretty simple and then just cache those in in that method so you can do something similar to that and restructure your code if needed but i would say start with the singletons or at least start being open to them at least if you're not and if you haven't been convinced at all please argue down below and let me know because i'm curious if everybody totally disagrees or um if anybody has been maybe convinced also don't forget to check out cyrenix and the new odin validator their products will help you speed up your workflow just like they do for me so click the link in the description below to check them out
Info
Channel: Jason Weimann
Views: 17,083
Rating: undefined out of 5
Keywords: unity, unity3d, odin inspector, singleton, singleton pattern, c#, unitysingleton, monosingleton, odin inspector custom, unity inspector, odin, unity scriptable objects, static variables, mono singleton, dani, game, unity tutorial, brackeys, tutorial, code, game development, jason weimann, unity3d college, game dev, dev, gamedev, unity 3d, game development unity, tutorials, game programming, how to make a game, devlog, unity technologies
Id: Bl0er8-qbOc
Channel Id: undefined
Length: 16min 48sec (1008 seconds)
Published: Fri Aug 26 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.