Truth about Singletons in Unity | New GameDevs WATCH!

  Рет қаралды 17,448

Jason Weimann (GameDev)

Jason Weimann (GameDev)

Күн бұрын

Пікірлер: 132
@PetersKotstube
@PetersKotstube 2 жыл бұрын
I've decompiled many Unity games to look at the code for learning purposes. Almost all of them use singletons. Just to mention some popular ones on Steam: Cities Skylines, Endless Space, Plague Inc, Subnautica, The Forest, 7 Days To Die. These are actual successful projects and then you have people with nothing to show who are telling you that singletons are so bad. Some people get things done and others just talk.
@adventuretuna
@adventuretuna 2 жыл бұрын
Yep armchair programmers are like that.
@Josh-gb9ml
@Josh-gb9ml 2 жыл бұрын
Reading through all these comments I haven't seen a single one that's convinced me they are "bad" in any way. It's all just "well it Might cause a problem when x and y and z are a thing". Like okay but literally everything in programming Might cause a problem under specific circumstances that's how programming works. If you use singletons correctly they're perfectly fine. If you don't they're not. Who woulda thunk.
@kostas1003
@kostas1003 2 жыл бұрын
Game studios often have deadlines to follow which forces developers into caring less about architecture and just getting it done. Often developers use singleton for a prototype and hope to refactor later. However, that never happens, as the business side of things don't see a need for that and can't comprehend the problem of scalability in software engineering. I wouldn't assume developers coded it in the way they wanted to.
@sisus_co
@sisus_co 2 жыл бұрын
I feel like debates about whether singletons are an anti-pattern or not often miss the point. They tend to focus a lot on the "ensuring that only one instance can exist" point (or if not that, then the "static variables are bad" point), which I don't think is in practice at the heart of the issue. The biggest issue in my experience is that using the singleton pattern can easily lead to a great number of classes being tightly coupled to a specific implementation. This makes the code a lot less flexible in comparison to working with injected abstractions. So the issue with using InputManager.Instance everywhere isn't that you might need to have multiple InputManager instances exist at the same time during gameplay. The issue is that writing unit tests for all the thirty classes that use the input manager becomes much more difficult. The issue is that you can't easily swap the input manager with an TouchScreenInputManager in mobile builds and GamepadInputManager when a controller is plugged in. The issue is that you can't reuse that Movable component for your enemies, because it's tightly coupled with the InputManager class, and can't be easily rewired to be driven by the AIController instead. The issue is that you can't reuse any of your classes in other projects when they have direct references to the InputManager class. The single responsibility principle is often cited as criticism against the singleton pattern, but I think it's really the dependency inversion principle and the interface segregation principle that tend to get violated more when singletons are used a lot in a project.
@marksmithcollins
@marksmithcollins 2 жыл бұрын
The real issue is scrutinizing "why, flexibility?"
@SunSailor
@SunSailor 2 жыл бұрын
I moved my team from the use of singletons to a service locator pattern. We have exactly one singleton in the project, which primarly acts as a service broker to the rest of the game. This manager can provide services with a singleton status, but they don't implement a singleton behaviour. So they are easy to test and can be isolated not only in the application scope, but a threaded or object scope as well. As we are aiming for a deep test coverage, this was a little game changer in the system design.
@UnitCodesChannel
@UnitCodesChannel 2 жыл бұрын
Hey Jason! These are some good points you have highlighted in the video. However something to add in the ending statement from my limited experience is that, if you're finding yourself re doing a lot of same type of instances with minute feature changes and saving their referenced data, please consider using Scriptable Objects, which also has added benefit of persisting data through scenes. "Scriptable Objects", please have a look once as its nothing more than a template to store, use & persist data throughout levels/scenes. You can also use JSONUtility to store data but that according to me feels one step higher than Scriptable Objects since they have a little more setup time. So I urge you to give a look into the Scriptable Objects, after you understand singletons and use them extensively in your game. Eg: If you have superman and batman both in a single game, you can create a player scriptable object, and then decalre variables of type, special power, speed, strength, etc. Then all you need to do is create a SO once and re use the template for protagonists and antagonists, or even if its a card game. You will save a lot of mess in long term. So, conclusion of this comment: 1. You could use Singleton for things like: Game Manager, Scene Manager, UI Managers, etc for all Managers, 2. For dynamic data holders like players, enemies, multiple types of enemies, etc, try to use Scriptable Objects. --- Thanks for reading, I hope you finish your game rather than wait for it to be perfect and get stuck between "Imposter Syndrome" & "Analysis Paralysis". Happy Dev'ving! Cheers :D
@michieal221
@michieal221 2 жыл бұрын
I fundamentally agree with this. Singletons are perfect for a Manager. The real issue that I see in programming - from database applications for the Auto Industry to game development - is that people like quick references and love to go overboard and make everything a singleton. I also really like Scriptable Objects for starting data... Such as the player's starting stats, or even in the instance of a recent project that I worked on, the base state for a room's description in an old-school text adventure game. I will point out, though, that with using Scriptable Objects, that you create a working class that imports the data from the Scriptable Object as needed. Noting that Scriptable Objects are static at runtime in Unity.
@93Ryans
@93Ryans 2 жыл бұрын
Whether or not to use singletons is all about the scope of your project and the size of your team, in my opinion. If you're prototyping or working by yourself and REALLY know what you're doing, architecture-wise, then they're fine. But if you add even one other programmer to the mix, or if you're working on a project that you think or even just hope might expand in scope, then you're playing with fire. Lots of people are taught that singletons bad, but unfortunately I don't think people can properly learn that lesson without being made to maintain and untangle a system that's gridlocked by overreliance on its global state. I'd urge everyone to consider a Service Locator pattern as a compromise. And don't gloss over the part about delivering abstractions and interfaces instead of hard classes. Edit after watching: I like your advice to use them when appropriate and refactor when needed, that's a nice compromise for scope expansion. And it's one you can't do with normal static classes. My only addendum would be to be mindful when implementing and referencing a singleton, of what that refactor would look like. Grabbing and caching an instance in one line is easy, but if every time you access it you're doing it via "SoAndSo.Instance" then it'll be a huge pain. So if you use em, I'd say treat em like member references that are being grabbed early on, and not like static systems that happen to have a global instance. Also, I'll agree that the S in SOLID is the one I take most liberties with. I prefer to think of it like "a single object should have a single *general* responsibility, and each method within that object should have a single *specific* responsibility that's part of that general responsibility". Making an object whose entire job is to do one tiny specific thing for another object that could easily just do that thing itself with one method is asinine.
@abalorias333
@abalorias333 2 жыл бұрын
This, In my experience if you have a big team with many ppl and multiple systems reused across different games, all these “Criticism” points shown in wikipedia start to make sense. But for many smaller indie games, Its not really relevant so just use them until you see the problems :)
@kantagara
@kantagara 2 жыл бұрын
We have 6 developers in the team and are extensively using singletons for some single-instance-per-scene classes (for things that persist troughout the scenes we don't use monobehavior but just static classes), and they proved to be really good at that and we'll still continue doing singletons where they make the most sense.
@davidclark1775
@davidclark1775 2 жыл бұрын
IMO, we need to split the discussion into two pieces: singleton behaviour and global variables vs dependency injection. Singleton behaviour should derive from the semantics of the object, not from the use context. Perhaps a class manages an external resource that only allows one manager. Perhaps it represents a transaction log and we want a single integrated ordering of events. Perhaps it manages a serial port. For those, having two objects could arguably break or complicate the design. The second issue is how we get access to the object. The so-called singleton pattern is based on global name access. The objections to the pattern are really objections to global names/variables. I agree wholeheartedly with those objections. So, create singletons when that matches the underlying semantics but don't use global names. Instead, create your objects, singletons or not, and inject those into the required contexts. Little more complicated but well worth it. The ShipActionText example is not semantically a singleton. There is no reason to disallow having multiple on the screen. So create it as a non-singleton, one if you only want one, and then inject it into the contexts where it is needed.
@b4ux1t3-tech
@b4ux1t3-tech 2 жыл бұрын
Well said! I came here to say that singletons are usually just the first step to dependency injection, and shouldn't be feared. Nice to see someone beat me to it.
@AlCh3mi_MvP
@AlCh3mi_MvP 2 жыл бұрын
Great info! The only draw back for me in unity when using Singletons is, when making a test scene, or I just want to quickly drop the player in an environment. But player references Input Handler Singleton, so I put it in the scene. Then it complains that it needs AudioManager Singleton, so you bring that in, now UIManager is needed, and eventually you're rebuilding your whole game in a scene just to test something. I have found the Broker pattern, or project space UnityEvents on ScriptableObjects to be preferable alternatives in Unity.
@midniteoilsoftware
@midniteoilsoftware 2 жыл бұрын
Tarodev showed a really good pattern that eliminates this problem. Create a single root level prefab with a script that's a public static class with a public static void Execute() method which in turn has the RuntimeInitializeOnLoadMethod attribute with a value of Before.SceneLoad. This method loads the prefab from the Resources folder, instantiates an instance and calls DontDestroyOnLoad on it. This prefab has all the managers you want to exist in every scene as children. This automatically loads when you start your game and they will persist across scenes.
@AlCh3mi_MvP
@AlCh3mi_MvP 2 жыл бұрын
@@midniteoilsoftware oh right, I think I actually saw a bit of that vid. It's interesting for sure
@supercyclone8342
@supercyclone8342 2 жыл бұрын
@@midniteoilsoftware Interesting... I already have all my manager objects stored in one prefab, so when opening a new scene all I need to do is drag in the player prefab and the "master" manager prefabs. What you said just automates the dragging in part, right? Also @AlCh3mi, someone else mentioned that it's a bad idea to have Singletons that rely on other Singletons, and I guess that's why! Though if your Singleton chain is always grouped (like mentioned above) then it probably won't be so bad.
@Sylfa
@Sylfa 2 жыл бұрын
@@midniteoilsoftware 18 months later, "why is the game crashing when I change the name of the end-boss music file?! It's not even used anymore!" It does sound like a nice way to avoid having to have the game crash X times before you can even get started with doing whatever you made a test scene for in the first place though.
@RaistlinMaj
@RaistlinMaj Жыл бұрын
At least the video is about Singletons in Unity. All the Criticism in the wikipedia article is valid and has important points on why you should avoid it. I've worked on the video game industry and there the Singletons became super handy because as you mentioned, you usually want one instance, there are not really concurrency issues (at least 10 years ago), and another important point, you control your whole framework. I'm trying to learn unity and ue and there, I can see singletons everywhere, but there is a big constrain, it is their own framework (I don't want to talk about the syntax of the unreal engine as I may go in a rant for hours) One thing I've seen with that pattern, is the fact that people will start adding more static functions and using them. This is, imo, the biggest problem with the pattern. Depending on the language, you can use frameworks for DI (dagger/guice in java for example), use the singleton annotation, and make a singleton instance of a class via DI, without actually using the Singleton pattern. That is a way more elegant way as you can still mock, respect all other principles etc. The concurrency aspect may not be relevant for your use case but it has been a massive problem for systems like python, boost c++ asio performance on unix, etc. They went with global single instances to keep secure some sections instead of attacking the problem with context/per thread system. Recent improvements on those platforms come from the fact of either getting rid of that single instance, or completely reworking that area to avoid the context switch hammering because of static instance (singleton). I've worked on alexa presentation layer core system and one of our rules was that singletons were forbidden (and usually statics that hold any kind of logic besides any utility) because of performance. I wrote some part of kernel modules for ecs instances where singletons were forbidden because of the same reason, concurrency and performance. Recently I migrated a whole telemetry layer from singleton to context system on c++ to allow better concurrency, improve performance and, make the system easy to scale across regions. Another reason is having a deterministic life cycle on your instances, with singletons it gets trickier (you can somehow simulate it, but you still depend on the compiler/gc to mark when is going to get released or invalidated). Another problem I would remark is if you force them in libraries in your public interface. You are forcing that pattern in your consumers, you are making testing for them harder and should be avoided (specially if as I mentioned, you don't only expose the getInstance, but extra static methods, thing that happens 100% of the time with this pattern) The only thing I would give to people is the smaller size of the instances as you no longer need a pointer/reference in your object if you use DI (you can save ptr_size bytes, and possible alignment space, per instance, thing that may be important on systems with constrained resources). Again, I've only seen that writing software for traffic signs where the memory was so limited, I had to squeeze every single bit out of it. Having to inject a dependency should not be seen as something negative or a waste of time but as a good practice. One important fact that you mention in the video is the lack of testing in the game industry and that is sad but true, mocking is seen as a waste of time or something complicated but it helps so much to detect regressions or bugs that I would love to see more systems to help with that on Unity/UE. My point is that, the only reason to use singleton is for convenience at the cost of other important things that on any big system will out-weight that little convenience.
@cfffba
@cfffba 2 жыл бұрын
When I started gamedev I loved them and used them for almost everything. That of course backfired badly more than once so then I went through a phase when I stopped using singletons altogether. It took me a while to find a middle ground between these two extremes. Now I use them sparingly only when they're the right tool for the job. They're not evil if you use them right. I prefer the service locator pattern though.
@Sylfa
@Sylfa 2 жыл бұрын
I've found that having proper unit testing makes maintaining a 300k lines of code project so much easier, without testing you have to double and triple check so you don't cause a bug that could result in massive losses if you push it live. With proper unit testing you have a safety net of knowing that, while it's not impossible to get a bug, you at least don't have to remember that edge case that had to be handled gracefully that you put into the project 2 years ago. Granted, bugs in a game just don't have the same financial cost to them, but there's other benefits of unit testing such as quicker code turn-around, functional documentation for team projects, and so on. I'd prefer a look into inversion of control and how to implement it with game engines over a discussion of globals, that would allow "global" objects but also allow for unit testing at the same time. Though to be fair, that's basically what unity/godot/etc editors give you, allowing you to drop in references for your scene instead of having the classes grab a global reference on their own. The biggest problem with globals is the non-locality of bugs, all you have to do is a silly mistake like adding a ++ in a UI elements script, then after having pulled up some of the functionality into a base class you go to reuse that display script on a similar object, and suddenly you have enemies sliding through the walls when you open the inventory page, and simply no idea how that's even possible.
@ADreamPainter
@ADreamPainter 2 жыл бұрын
You did leave out a couple of extra things I sometimes add to singletons. Specifically, before I say "instance = this," I will usually write (If (instance != null && instance != this) destroy(gameobject); This is helpful for debug reasons with games with multiple scenes, of course I also add the "don't destory on load" flag to keep the singleton loaded across all scenes.
@VanessaMoonveil
@VanessaMoonveil Жыл бұрын
About to switch my player to a singleton, wanted to know more about them before doing so. I'm pretty convinced tbh, I see no issues for what I need it. great video!
@mattsponholz8350
@mattsponholz8350 2 жыл бұрын
Of course the principal that's saved me the most dev time in my games over the past several years is the root of an argument 😅 Great video, Jason! Thank you!
@tofaani
@tofaani 2 жыл бұрын
This channel is goldmine. Old is gold !
@seppukun208
@seppukun208 2 жыл бұрын
I always cache them if possible just like any other component. Makes it extra fast to refactor if I decide not to use singletons and de convert the object.
@libberator5891
@libberator5891 2 жыл бұрын
4:50 slight correction: you can definitely do lazy instantiation in a public getter, it's just new GameObject(). And then an AddComponent to easily get the reference to the singleton. I've never had issues with it. Only downside to lazy instantiating is you won't have any editor-populated values (like project assets or scene references)
@Unity3dCollege
@Unity3dCollege 2 жыл бұрын
Good point. I was thinking of objects that needed other setup in awake, but totally forgot to explain that reasoning. Thx for the correction!
@maxfun6797
@maxfun6797 2 жыл бұрын
@@Unity3dCollege Sorry for asking this in the youtube comment section, but can you make a video on "How to name methods/method naming convention". I find this subject more complex than it sounds up front and the simple "name after verb" solution. Get for getting vulue, set for setting. "calculate" for Math opps? and what if a method does multiple things because it is a header method with a few local methods. :)
@mattwhiting2205
@mattwhiting2205 2 жыл бұрын
@@Unity3dCollege I take it even a step further. If you put the prefab for your singleton into the Resources folder, you can have the singleton load itself in the getter! This is particularly useful for those managers that you have to add to every scene... those can be a real pain for all the devs making test scenes that break over time because they forgot to add some singleton in there that you're dependent on.
@N4m43
@N4m43 2 жыл бұрын
@@mattwhiting2205 I find it a lot better to have a scene holding all managers that is never unloaded (additive scene loading), and have singletons on these managers (or even better: having an InstanceManager that holds the static references of all your managers). This even allows you to preserve the state of your managers between scenes.
@mattwhiting2205
@mattwhiting2205 2 жыл бұрын
@@N4m43 Yep. That's a good method too. Although I use DontDestroyOnLoad() to preserve the state between scenes.
@vyse-sen
@vyse-sen 2 жыл бұрын
jason you are 1000 men * by 1000. ur videos have inspired and helped a gamedev here ina very positive way. thank you
@Gamovore
@Gamovore 2 жыл бұрын
Before going deep into the video here are my thoughts. First I'm a professionnal programmer. I currently work on a triple AAA game but I'm still a junior and still learning. The truth (for me at least) is that seniors always tell you that theoretically things are bad because bla bla bla but in fact it's used in the biggest projects of the industry. It can be a problem in very specific cases but for most programmers on the project it's never been and will never be a problem. I think as programmers we just ask ourselves too many questions. We definitely need to think a lot about the hierarchy but we shouldn't overthink it. A singleton never killed anyone. People told me so much they should be avoided that now I usually have one singleton in which subsystems are registered and then I can access those subsystems from it. But when I think about it I don't even know if that would be a problem if all of those subsystems were singletons themselves. It's just an habit thatt I have and it's not even mine. By experience (as little as mine is) I can say that the more complex your code is the less understandable it becomes. I often see automated system that are a big problem for us because we don't have any flexibility and can't custom any behaviour for special cases.
@jeffmccloud905
@jeffmccloud905 2 жыл бұрын
at 8:30 ... that works of course (causing a deliberate compile error to find where the code is being called)... but your IDE can do this too. You can right click on the method and choose Find Usages or Find All References
@Sylfa
@Sylfa 2 жыл бұрын
As long as your project isn't in multiple compilation units, yes. If you split it up into several DLLs and unload some of them to reduce the compilation times then you won't be able to find them like that. It depends a bit on how you're compiling things if it helps to add a compilation error though, changing from public to private and then fixing each module one at a time should work.
@bryansaur8793
@bryansaur8793 2 жыл бұрын
I personally use them in pretty much every project. I usually limit them to manager classes and have nothing but good experiences that way.
@Joooooooooooosh
@Joooooooooooosh 2 жыл бұрын
Honestly, if Unity would embrace dependency injection the way .NET core did, singletons could largely be replaced by scoped dependencies. There are some DI solutions in the asset store, but it really needs to be built in so that everyone can standardize on a single container / service provider.
@syriuszb8611
@syriuszb8611 2 жыл бұрын
Multiple instances are easy to work around, just make your singleton a middle man that holds list of those instances, and maybe manages them for singleton purposes. Like instead of using singleton Team, use singleton Teams that holds a list or array of Team. Also, in Unity we can use Scriptable Objects as sort of singletons, you usually still need to reference them manually, but you can reference them outside of scene, so it's easier to do. And then, when you need MonoBehaviour, you can just register it on awake in that SO and access it from any place that uses this SO. It's a little more work, but it works great, and you can make a MonoBehaviour "socket" for that SO, so at init of your game, the socket registers in the SO, make anything that Monobehavioiur can, even Update() {SO.Update()}, and it can also make on awake static instance that you can access just like Singleton. Of course, you need to check if you don't have multiple SOs when not intended, but this shouldn't be an issue.
@michieal221
@michieal221 2 жыл бұрын
The real issue that I have seen, is that people figure out singletons, and then use it for everything. Especially, if they come from a global access background, like a Visual Basic programmer. (Nothing against them... I love me some VB.Net. lol) But it seems that the quick reference, rather than searching for things reference-wise, seems to create this effect. In trying to answer that for my students, I created a "Linker" game object. It's a singleton that goes out and grabs references to objects in the game, to be a roadmap for the rest. Kind of like the nervous system connecting the brain to the hand, or a finger to have a pathway to the foot. Doing this architecture node makes it to where there's a lot less singletons floating around, improves the ability to quickly get references to something mapped from anywhere, and in practice simplifies design modalities while keeping speed. It can also be dynamic, as when the object is (re)created, it can map itself to the linker. After creating the idea for my students, I started doing it in my unity projects, as it made work while testing a level or debugging, as the compilation process breaks reference connections when playing in the editor. So, to me it speeds things up as I can just pause, tweak the code, pop back in, and resume play again.
@SkinnerSpace
@SkinnerSpace Жыл бұрын
After watching this video I get convinced that singletons aren't that bad as I suspected them to be. The problem with singletons in my projects is caused by their quantity that can be reduced by binding of some of them . Thanks for the nice explanation!
@AJ213Probably
@AJ213Probably 2 жыл бұрын
I would agree on the unit testing downside when I do want to unit test in Unity. But it's rare for now. Do want to test more...
@synchaoz
@synchaoz 2 жыл бұрын
Writing this at the start of the video: I'm at intermediate level unity/game dev I would say, with 3 years experience, and I use a singleton in my project. I don't fully understand what the big deal about them is, hence why this video is exciting to me. If I feel I need more than 1, I will probably make more. At least that's my standpoint right now. We will see at the end of the video where I will update this comment. After watching: I don't feel my stance has really changed. I find the one I have useful, although this video has opened my eyes to ideas that would allow me to probably get rid of it. My use-case of it seems sensible enough though, as it's really just a singleton that holds some dictionaries used for saving/loading temporary object state data between scenes that doesn't need saving on disk. I can better understand how they can get out of hand in a negative way after watching the vid, but I feel like the tribalism mantra of subscribing to singletons being universally bad is a bit hyperbole. Use them if they benefit you and you can manage them.
@Sylfa
@Sylfa 2 жыл бұрын
Singletons are one of those design choices that are perfectly fine to use, as long as you can keep all the use cases and edge cases in mind. And that's the problem, by the time you realise you've lost track you've already gone far off the edge, Wile E. Coyote style. That's why it's an anti-pattern, not because there's no good use-cases at all, but because it's way *way* too easy to underestimate the scope of a project. And then when you're trying to get the final 5-15% of the game finished you start running into issues where a variable is changed where it shouldn't be because "it's late, I'll just add it here and fix it tomorrow." And now you're stuck paying technical debt for early design choices, long after you've forgotten the exact places you're even referencing said class, at the same time as you're trying to not delay your game release. For a small project that you're not going to work very long on and you're basically the only developer, it's perfectly fine. Perhaps you could even get away with it for a medium sized project, or one with a small team of developers, or one that you're working on for a bit longer than normal. But probably not more than one of those at once, and certainly not all three at once. I mean, if you really think about it, private/public, inheritances, interfaces, and so on are all just restrictions placed on the developer to guarantee that the code makes sense. You can certainly just compile C code into an .obj file and load it at runtime, I know I did and it worked great! For a small mini-game that only took a week to write. Or write functions in assembler and have it run fine as well, did that too but not for a game. All of the higher language features are there to help find bugs and to help organize your code so it's easier to maintain. As the saying goes; you only write a line of code for a few seconds, the rest of the weeks, months, or years you're maintaining it. PS, it might sound a bit harsh, but I'm just trying to help you - and others in your situation - to avoid discovering where their limits are by failing a project in the future. As long as it really does work for you it's totally fine. Just know that you won't be able to see when the problems will start before hand, but after the fact. That's why it's an anti-pattern.
@chooseareality
@chooseareality 2 жыл бұрын
I think they are like most things in software engineering and need to be considered another tool in the toolbox, but should never be the only tool you use, or the tool you never use. I have worked at places that had a "NO SINGLETON SHALL EXIST" rule and it did make things very good at separation of concerns and single responsibility, however the initialization and loading of all the things and passing around of things created a lot of overhead where making one or two singletons would have made things so much easier to access and debug quickly. I am always wary of any rule that is absolute when talking about software. It feels like Dogma and not logic when entire patterns are thrown out because they can be used badly.
@DevDunkStudio
@DevDunkStudio 2 жыл бұрын
Also amazing to use these in rapid prototyping
@nick-xw3yo
@nick-xw3yo 2 жыл бұрын
I love singletons, so long as you have a grasp of what they are and how they should/can be used, they are great. Just if you are working with others you have to be careful.
@badbanana9894
@badbanana9894 2 жыл бұрын
Really decent description of this function. Much better than reading the api Thanks
@daveblack5211
@daveblack5211 2 жыл бұрын
I like make my factories classes singletons, as it helps a lot when making my own dependency injection.
@N4m43
@N4m43 2 жыл бұрын
One danger I found with singletons is when people start using them in "generic" classes (not talking about the thing, just classes that don't seem to depend on a specific context). In my current job we have stuff like that... There's a class that creates data for a level. Instead of specifing said level in the constructor (or an Init function, whatever), we use the singleton of the currently selected level. This is absolutely terrible, as it pretty much makes unit tests impossible... Of course there's a workaround, the singleton isn't actually read-only, so we can set it to the desired value then run the class, but it's an awful design (+ the singleton needs some dependencies). It shouldn't be like that... This class should be able to use any level at all, and when we use the class in the actual context of the game, there we should use the currently selected level.
@goldone01
@goldone01 2 жыл бұрын
I'm personally fine with singletons but only in very small games and where you are certain they will remain small. A singleton actually has two features - 1) it ensures there is only one, and 2) it makes it easy to get a reference to that instance. I feel like most people use it for the latter reason, and that can cause problems. Because it is so easy to get it, you spread dependencies much further than you would otherwise need, and become very dependent on the concrete implementation of your singleton. Yes, refactoring each use is easy in a sense that it's easy to find, but it is not at all easy if you change how your singleton works.
@Sylfa
@Sylfa 2 жыл бұрын
Yeah, I've seen examples where they've combined public members and singleton and throwing it around all over. You're just one "this variable can never be ____, so I don't have to check for that" away from adding an edge case that will somehow months later make link slide across the whole level if you open the menu at just the right time while blocking…
@UTFapollomarine7409
@UTFapollomarine7409 Жыл бұрын
love your content bro
@SmashedHatProject
@SmashedHatProject 2 жыл бұрын
if it already exists it will tell the caller, if it doesn't, it will create it then tell the caller.
@Hennadii_S
@Hennadii_S 2 жыл бұрын
3:56 constructor is doing nothing, BUT it is private, it is matters.
@MysticThistle
@MysticThistle 2 жыл бұрын
My major gripe with singleton design is that they accumulate irrelevant stuff over time just due to laziness. It used to happen to me where I'll just add another field "quickly for now". They are just 'technical debt' farms & it really doesn't take much effort to think of an alternative approach
@FileTh1rt3en
@FileTh1rt3en 2 жыл бұрын
If you don't mind me asking what are some good alternative approaches you have? Personally I feel like I have to use singletons or do something even worse, searching through objects using GameObject.Find or FindObjectOfType. I use Singletons somewhat liberally, but my general purpose is I typically have one that holds references to things in the scene. This is so that I don't have to go searching through the scene for things. The reason I need a ReferenceManager singleton is if something is spawned later in the scene, like a networked player, and it needs access to stuff in the scene, I think it's much nicer to ask the singleton manager for the reference. I know of the ServiceLocator concept but I feel like it's not quite the same and it seems like the versions I've seen of it are a little convoluted. On the contrary I don't really have a heavy singleton concept. I like Jason don't make the singleton responsible for deleting others or instantiating a new one. It's basically just a global accessor that I'm after.
@MysticThistle
@MysticThistle 2 жыл бұрын
@@FileTh1rt3en I wouldn't make a habit of doing Find or FindObjectOfType other than caching references at Awake, it's quite CPU intensive. There are many alternatives so it really depends on what you're trying to do. You could have a static field within a MonoBehaviour instead, which would be accessible to every instance of that class without needing to have an additional singleton object (which brings in the Singleton state considerations). You could use the listener/observer pattern, if this goes far enough you could design your game more around event proxies using ScriptableObjects to avoid spaghetti coupling. You could use dependency injection which is quite popular (since it is really good for setting up Unit Testing - expert mode engaged IMO). You can also be creative in the Unity engine itself, with things like layers so you just know every object in the Units layer has a "Unit" MB on the transform root, but this takes conscious design effort. There's probably loads more I don't know about, but hope these ideas help
@manzell
@manzell 2 жыл бұрын
I like to use static classes, which in practice isn't that different from a singleton but feels cleaner.
@Sylfa
@Sylfa 2 жыл бұрын
That *is* a singleton. Or, I should be specific, that *is* a singleton if your class is stateful. Ie, has static variables.
@nowayjosedaniel
@nowayjosedaniel 2 жыл бұрын
@@Sylfa It is what it is. Static classes.
@aaronperron
@aaronperron 2 жыл бұрын
singletons save lives!
@goehlergamedev
@goehlergamedev 2 жыл бұрын
I've used Singletons quite a bit. A bit too much sometimes actually. When it's one of the first patterns you learn, you just start using it for everything - even places where another pattern would be better. And I think that's why it gets all that hate - and then later, some people just go totally nuts and stop using it all together - even in places where it would be the logical choice.
@dbweb.creative
@dbweb.creative 2 жыл бұрын
Would a static class be a good idea to contain references to various "global" things? Perhaps then wouldn't even need a singleton, because you could make instances of things like game, ui and other managers, and then store references into a static's field/array/dictionary. I've been pondering this idea and don't know if it's ok to do this kind of thing.
@Unity3dCollege
@Unity3dCollege 2 жыл бұрын
That's pretty common. I tend to do a few small static classes that have references or a property on the class that's static like in the video myself.
@supercyclone8342
@supercyclone8342 2 жыл бұрын
Oh, wait! I started typing something, but I think I get what you mean! Instead of making my Player script a singleton, I could make a static "ReferenceHolder" class or maybe a specific "PlayerInfo" class. I might do that... It's even easier to type too: Player.instance.motor becomes PlayerInfo.inputController. You could also have PlayerInfo.input, PlayerInfo.rb, PlayerInfo.stats, etc. In some cases, you could make the all the scripts attached to your player into singletons, but that sounds messy. And in my case, the player shares some generic scripts with other gameObjects, so that wouldn't work anyway.
@niederbayer2141
@niederbayer2141 2 жыл бұрын
Curious what you would do in a case where two classes want to set Player.Instance.transform.position and only one is allowed to because of some condition. This needs to be managed somehow and it can get complicated. I would register the player in a static class where the player state is stored. This class would then decide who is allowed to set the position (kind of MVC)..?
@arunachalpradesh399
@arunachalpradesh399 Жыл бұрын
i directly use static class like old way of coding instead of singleton.
@D-Dev
@D-Dev 2 жыл бұрын
From my point of view, singletons are not bad, of course we have many other patters that allow us to achieve same result and are also more elegant cleaner and so on, but they are olso more complex and abstract. So the singletone pattern is a great way to start prototyping somoething and when you have something that works you can start thinking about nicer and cleaner architecture. ;)
@Sylfa
@Sylfa 2 жыл бұрын
As long as you use the mentality of a spike in agile programming you can do it any way you like. The idea there is that you throw away the code afterwards and rewrite it properly. If you let yourself keep the code to "copy the working parts" then you're just one step away from "well, that bit is working fine after all."
@goldone01
@goldone01 2 жыл бұрын
I think this calls for a poll
@digis_monkey_king
@digis_monkey_king 2 жыл бұрын
Actually I only recently realized I was using singletons... I use them when the player enters a new scene, so when the player returns to the previous scene there aren't two of them. The only time I ran into problems is when I wanted to test the player in a specific scene and forgot to remove it, which caused inconsistencies when using code to position the player, thinking it's origin was in another location. so, what i'm saying is, there's no reason it should be bad, unless of course you were unaware of it's being used like I was. If you're going to use singletons, make note of where you used it to make sure it doesn't affect your projects negatively...
@Sylfa
@Sylfa 2 жыл бұрын
There's nothing wrong with singletons in any project, as long as you're never unaware of all the edge cases in every class you've ever written for the project. And that's the problem with it, it works perfectly fine and reasonably until it doesn't. And at that point you're in for a lot of project delays, unexplained bugs, one-off bugs, race conditions, "magical button combinations" that send link/mario flying across the level, and so on. Of course, avoiding the pitfalls is easy when your just getting started, especially given that it literally is fine in smaller scopes, it's not until it's too hard to keep everything in mind that it starts breaking. Or rather, by the time the bugs start showing up you've already gone past the point where it's easy to fix. So then you have to decide if its worth taking the time to just patch the bugs as they show up or if you need to sit down and take weeks to really fix the underlying problem. There was actually a pinball game back around the year 2000 that was written twice, the small independent development team had nearly finished the game when they had enough and started over from scratch. They literally couldn't get the game working well enough with their initial attempt at writing it, they had underestimated how much bigger the project would be in the end and had made some poor design choices early on. I don't recall them ever going into specifics about it, but it made national gaming news over here as it was practically unheard of a team doing that. Game turned out great in the end, can't recall what it was called but it was made by a Swedish development team.
@nukode-5974
@nukode-5974 2 жыл бұрын
+ Unit Testing is not the only way of Testing.
@mehmedcavas3069
@mehmedcavas3069 Жыл бұрын
I think that that singletons are neighter good or bad they just have a purpose. I almost never use them but its just because I never needed them but if I would use them I would create singletons for non gameplay things. more like services or external tools. like analytic manager, network manager or a tool which I can use in other projects too. so not just its one instance but I also know that I will now have different type of analytic managers and so on. To game play related manager I generally use interface and connect them with dependency injection. thanks to this I can create test scenes with different type of manager values
@XaFFaX
@XaFFaX 2 жыл бұрын
In my view the discussion in regards to actual design pattern in context of Unity is pointless. The reason being that those are not "true" singletons but more like "Unity singletons". This is because you really do not have control over direct object instantiation in Unity (for game objects at least, you can make helper classes that are "plain" C#). That said the topic is null and void, since this is different type of pattern and if it is properly used in Unity, makes sense, does not cause problems then why not to use it? Another can of worms is that this CAN cause problems in Unity (one of such cases can be instantiation of objects in OnDestroy when such singletons are involved), however any type of pattern or solution to a problem can cause problems, so this is not really an issue. It all comes down to programming being difficult...
@dago6410
@dago6410 2 жыл бұрын
If I have manager classes, which would be my main usage of singletons, there is no way they would be monobehavoiurs. POCO for the win for anything that does not need to be a MB.
@TheMeeelting
@TheMeeelting Жыл бұрын
Singletons are fine but you need to know what you're doing; if you end up writing spaghetti AND using a singleton, odds are you're in for a bad time. But if you know what you're doing it's a very useful tool that leads you get ahead faster.
@SkinnerSpace
@SkinnerSpace Жыл бұрын
So, where am I at the beginning? I use singletons quite a lot but I'm suspicious that this is a bad coding practice. My projects are contaminated with differents kinds of "Managers" like: "Spawn Manager", "Menu Manager", "Environment SFX Manager", and so on. Let's see how my view will change at the end of the video and whether I'll do something about my singletons.
@CollinPatrick
@CollinPatrick 2 жыл бұрын
If you are going to make a singleton, make it a base class if possible. It prevents you from having to write the same code multiple times. public class Foo : Singleton {}
@SaudBako
@SaudBako 2 ай бұрын
The same battle fought in the 70s, but programmers' 2nd job is to repeat the past.
@maximeumbra7235
@maximeumbra7235 2 жыл бұрын
My view at 60 seconds: They're a tool among others, they pose some unique pitfalls and should be used when called for but one should never use them just because it's easy.
@maximeumbra7235
@maximeumbra7235 2 жыл бұрын
My view after: They're still a tool like any other, use them sensibly. And many of the arguments against them seem to stem purely from code religious dogma, if your thing by its very nature as a thing is something you would expect to do two things, have it do two things. The rules are there to guide you and make you Think, you cannot compose good software simply by religious dogma and while OOP is very powerful and useful it is by No means the be all end all of all other paradigms. There are plenty of environments where paranoid encapsulation IS The anti-pattern, the environment you code for determines what is a good idea not the level of abstraction which is environment dependent.
@markaldrich8753
@markaldrich8753 2 жыл бұрын
Comment before I start the video: Singletons are a valuable tool in a small project, but should be replaced in larger projects, because they're easy to modify from the outside, which isn't something you want in a project with lots of moving parts. Granted, I've never worked on a huge project before, so I'm interested to see what you have to replace them.
@Sylfa
@Sylfa 2 жыл бұрын
Inversion of Control, so that the class is given an interface it can work with, but doesn't know how to get it itself. Technically that's what you do in Unity when you drop in references to your MonoBehaviours, but you really want to pay attention to the open/closed principles and make sure to [SerializeReference] your variables, don't give yourself the option to "just add the ++ in the UI code for now, it's late and I want to finish this." I believe there's some frameworks that work in Unity so you don't have to drop in your fifteen references on every object in every scene, and instead have a dependency injection framework do it for you.
@valentinstudio3334
@valentinstudio3334 2 жыл бұрын
Yeah it seems on Wikipedia people simply aren't making games and are writing globally about apps or something I have 2 singletons in all of my games, one for the GameData (my save file basically) and one for my PlayerSettings (Containing all the settings of the player) All their arguments against is exactly the point of singletons IMO I think it's like everything, like interfaces as you explained in your other video, as long as you're not starting to use them everywhere for everything ... I think it's fine as everything as long as you're moderate ...
@MrZtapp
@MrZtapp 2 жыл бұрын
Why Singletons when you can use static?
@hassanmalek117
@hassanmalek117 2 жыл бұрын
Singletons makes life easy
@GameplaysJogosPC
@GameplaysJogosPC 2 жыл бұрын
Singletons are very good. It's a technique that works for specific things. There is no right or wrong in programming. All the criticism that was made on the singleton violates the singleton principle haha. just as design patterns serve as "guides" for the format of a project, they are not absolute rules, things can be modified, "principles" are violated in all projects, hardly a software or a game follows 100% to the letter all the standards because is impossible. Each project has its needs and each purpose, especially in games that are extremely different from software. Therefore, singleton concepts are very good and useful for specific things according to needs. A phrase that can sum it up well would be: "With great power comes great responsibility". If something has the need to be a singleton, it's definitely something important to the project.
@jankrajewski6170
@jankrajewski6170 2 жыл бұрын
I'm making a boss battle arena game, so in every scene there is ALWAYS ONLY one player and ONLY one enemy. Easy concept and even encourages using singletons for both, player and enemy, so as a begginer developer of course I used them. Since then I hate singletons as much as I once loved them. It made the game untestable. It's a small case scenerio, but I cant imagine having problems I had, but on a much bigger scale. Now as I plan my code base I always think, if the game will still work if this particular component suddenly dissapeares. This makes development much easier for me. Encapsulation is the key. At the end of a day I would say that it is much easier to write code and be concerned about how will it communicate with rest of the code base than write code and be concerned about how dependant it will be on rest of the code base.
@LukeClemens
@LukeClemens 2 жыл бұрын
If for some reason, you decide you want to make two boss enemies for a level, you'll wish it wasn't a singleton because it'll be a pain to go in and rewrite everything that depends on it.
@jankrajewski6170
@jankrajewski6170 2 жыл бұрын
@@LukeClemens yeap! Thats another problem. Code base that is so rigid prevents project from evolving
@marksmithcollins
@marksmithcollins 2 жыл бұрын
Great code does not guarantee YOU to finish your goal. Try to fulfill your goal unless someone in your team(including you) suffers from your code
@streamcyper
@streamcyper 2 жыл бұрын
Singeltons, is simply a tool, like pretty much everything else.... There's not really any bad tools, only bad use cases for that tool. Know it's use, know it's limitations, and use it where it make sense... That's how every tool should be used.....
@goldone01
@goldone01 2 жыл бұрын
Very true, but singletons in particular suffer from the "if you have a hammer, every problem looks like a nail" syndrome. Once you have a fully filled toolbox they can be appropriate, but especially for those starting out it can be tempting to misuse them
@halivudestevez2
@halivudestevez2 2 жыл бұрын
Now you have proved the ambivalent feelings about singleton pattern, it was suspicious for me. While it is comfy and handy to use, there are design problems with it, especially regarding dependency.
@JeffGraw
@JeffGraw Жыл бұрын
Singletons arguably have a place in and of themselves, but Singleton Monobehaviours are evil, hacky, and fragile.
@harmonicseries6582
@harmonicseries6582 2 жыл бұрын
Single responsibility principle is mostly a cargo cult opinion that has a lot of traction between junior developers, it is by definition ambiguous and there is no peer reviewed evidence to show it helps anything whatsoever.
@liolyne
@liolyne 2 жыл бұрын
It all depends of the number of reference you need to do. Like always it is balance. I try to avoid them because I really like my code tidy and not messing around with other part of code. And I prefer to use it to test something and then refactor in a proper script. A reference to an object is not that hard to do either and doesn't take that much time.
@PandoraStratos
@PandoraStratos 2 жыл бұрын
I prefer using the Doubleton pattern, it get's away with all the Wikipedia criticism.
@MasterofGalaxies4628
@MasterofGalaxies4628 2 жыл бұрын
The analogy I've come to adopt is that a non-game dev berating a game dev for using singletons is like a harp player berating a violinist for using a bow: singletons have more inherent value in games than outside them.
@vudshpreyk
@vudshpreyk 2 жыл бұрын
All your latest videos have audio out of sync
@Unity3dCollege
@Unity3dCollege 2 жыл бұрын
Strange, didn't notice. Will check out the video tool, wonder if it's broken
@eeevans
@eeevans 2 жыл бұрын
@@Unity3dCollege it’s in sync for me.
@rulypanda5318
@rulypanda5318 2 жыл бұрын
Lmao Im not alone
@nazar2383
@nazar2383 Жыл бұрын
4:17
@jtmcfarland3512
@jtmcfarland3512 9 ай бұрын
Saying Singletons break the single-responsibility rule is like saying all variables break it too because they require accessors. That’s the weakest and most flawed way to see it.
@Vicente_Lopes_Senger
@Vicente_Lopes_Senger 2 жыл бұрын
I'm sitting here considering converting my whole project to a single monobehavior class using partial class just for the joy coding and people are still discussing if singletons are problematic? No. Singletons are very useful. Every game need global states, data. That said, in most cases you would use a singleton you could probably do better using a static class. For instance, if you want to keep a lot of object references you can keep them in a public static class that can be accessed by any class anywhere. If the objects are monobehaviors they can set their own static references in your static class using their Start() methods. Like: void Start (){ StaticClassX.object1 = this; }. Coding, especially if you are indie or solo is about what is both more fun and productive. Following strict arbitrary guidelines made by other people make no sense when you have complete control of your project. Do what you feel is the better solution for the time being and do refactoring on the project as needed.
@ggre55
@ggre55 2 жыл бұрын
U talking too much without doing anything I had to imagine everything in my head and all possible scenarios depending on what u said but I'll never know if it's the right way to do it So in general u Just wasted my time
@GameDevNerd
@GameDevNerd 2 жыл бұрын
First of all, don't even write "TypeName.Instance" everywhere, just define a readonly static property as a shortcut/alias like this: static SingleThing theThing => SingleThing.Instance; Then you can actually write methods in your client classes in such a way that they just accept an instance of that class and they _don't need to even know_ that it's a Singleton or that it has a static property called "Instance", so you won't write that ugly crap all over your code, and you can keep access of your static "shortcut" property down to just a couple lines of code. If you decide to remove the Singleton pattern later because something else pans out that makes more sense, all you have to do is replace that static property with an instance obtained from elsewhere and your code is none the wiser: it just keeps on working as before ... The other part to this is don't _let_ people on your team misuse the objects, don't let them create more than one and get away with it: // inside Awake: #if UNITY_EDITOR || DEBUG if( isInitialized ) { Destroy( this ); throw new InvalidOperationException( $"A Singleton object of type {this.GetType()} was instantiated or added to the scene more than once!" ); } #endif If you wanna be a bit fancier, make a _SingletonBehaviour where T: Component_ class and make any Singletons you create inherit from _that_ instead of just inheriting MonoBehaviour, and then you can do some useful stuff keeping a static tracking List (which also tells you the Count) for the whole game, so you'll always be able to inspect the state of all Singletons inside the debugger and know how many exist, or you can iterate through them if you ever need to destroy all or certain ones of them. But if you have _a lot_ of Singletons, you're probably doing things wrong and just don't understand how instances and references work yet. I never have many Singletons, rarely more than 3 or 4 in an entire project. They can be used successfully if used sparingly and appropriately, and when you use them correctly you're able to write _less_ code and actually make it _easy_ to refactor if you avoid coupling everything to that static "Instance" property and write regular client code which doesn't care if it's a Singleton or not. Damn the criticism, I've shipped code utilizing Singletons moderately. And they're especially useful if creating more than one of something could have catastrophic results, like a C# object that implements IDisposable that's responsible for using a native library to load a huge amount of data to do things with it and make sure the native resources are cleaned up at the end. You definitely _don't_ want concurrent use of those resources in multiple instances because that could cause a total meltdown, lol. Some of those criticisms sounded like _strengths_ to me, at least in some very specific circumstances. Singleton abuse is an ugly thing, but so is MonoBehaviour abuse and coroutine abuse, two other things I really, really hate to see ... 🤢 For most projects, you probably only need 0 to 1 total Singletons. Just make your "Game" or "GameManager" the only one, have it create and/or cache references to those "audio managers", and other stuff you were tempted to make more Singletons out of (don't do it, lol), and expose the references to clients and be done with it so they only need to touch one Singleton (and shouldnt even know its a singleton other than that one readonly property you can easily replace) ... then you don't have tons of complicated webs of interdependent editor references or have to write any weird code do inefficient searches for references. For people who make _everything_ a MonoBehaviour and never write regular classes though, I just assume they're gonna go nuts with Singletons and write terrible code lol, as they already go nuts with MonoBehaviour and Coroutines _everywhere_ in a big heap of spaghetti 🍝 😄
@Braneloc
@Braneloc 2 жыл бұрын
Instead you could always do something along the lines of var notSingleton = GameObject.FindObjectOfType() ps. Is KZbin loosing comments randomly ?
@Unity3dCollege
@Unity3dCollege 2 жыл бұрын
It's moderation is not great. Catches good comments and let's some spam through still
@ezateldohimi423
@ezateldohimi423 2 жыл бұрын
I feel like you've covered pretty much all my use cases for singletons, i generally view them negatively. The global access feature is great, but i often find it encouraging bad patterns because when singletons add up, you can end up with multiple interdependent singletons which makes it really hard to debug. That still doesn't mean i completely remove them; UI Managers, Game Manager, Player Controller are essential singletons in every game, but i just have to ask myself two questions to confirm whether i really need to make this class a singleton; Are there multiple unrelated classes that require access to this one? Does this class depend on other singletons? My ideal singleton class is one that depends on no other singletons, and has a lot (+3) of other classes that depend on it.
@DoubleBob
@DoubleBob 2 жыл бұрын
You can have singletons depend on each other. What's the problem? I think the hate against singletons as a bad pattern is simply historic, when people were doing non-oop C programming and nobody considered read/write access roles in their code. Now we are smarter.
@killereks
@killereks 2 жыл бұрын
@@DoubleBob yup. Now we are smarter and have DI instead of singletons.
@someone.9290
@someone.9290 2 жыл бұрын
@@killereks i am just a beginner, how exactly do you use DI in unity?
@killereks
@killereks 2 жыл бұрын
@@someone.9290 most basic DI is simply feeding dependencies yourself. class UI { void Init(Player player){} } Then when u create UI u call .Init() This is much better than singletons because all dependencies can be seen instantly, and code is very flexible (u want StatUI? Do StatUI : UI and u have it.) Singletons make it very easy to intertwine code onitself, causing cyclic dependencies which is a real pain to fix on big systems. DI makes ur dependency graph tree one directional which makes it easy to scale code. I recommend zenject for unity, its free. It automates stuff i described but has a bit of a learning curve.
@someone.9290
@someone.9290 2 жыл бұрын
@@killereks thanks!
Why I Don't Like Singletons
29:05
The Cherno
Рет қаралды 89 М.
Unity3d - How to DESTROY a Game Instantly (Easiest Way) | And how to avoid
16:59
Jason Weimann (GameDev)
Рет қаралды 28 М.
1, 2, 3, 4, 5, 6, 7, 8, 9 🙈⚽️
00:46
Celine Dept
Рет қаралды 59 МЛН
PIZZA or CHICKEN // Left or Right Challenge
00:18
Hungry FAM
Рет қаралды 8 МЛН
Smart Sigma Kid #funny #sigma
00:14
CRAZY GREAPA
Рет қаралды 103 МЛН
Events or UnityEvents?????????
15:43
Jason Weimann (GameDev)
Рет қаралды 105 М.
Why I don't hate Singletons?
11:30
Jason Weimann (GameDev)
Рет қаралды 26 М.
Game Events - Power & Simplicity in Unity3D
17:15
Jason Weimann (GameDev)
Рет қаралды 73 М.
Better Singletons in Unity C#
14:08
git-amend
Рет қаралды 9 М.
When Optimisations Work, But for the Wrong Reasons
22:19
SimonDev
Рет қаралды 1 МЛН
Be CAREFUL with Scriptable Objects!
8:27
Code Monkey
Рет қаралды 83 М.
How to use Singletons in Unity3D without breaking everything...
25:34
Jason Weimann (GameDev)
Рет қаралды 52 М.
Watch This Before Working on a Big Game in Unity
18:44
John Leorid
Рет қаралды 299 М.
1, 2, 3, 4, 5, 6, 7, 8, 9 🙈⚽️
00:46
Celine Dept
Рет қаралды 59 МЛН