I've been searching for this video for so long. The perfect explanation that tied all of my entry level programming knowledge together in a nice bow. Thank you so much !!
2 года назад+164
Be careful about the static fields. They are preserved between level loads which may cause problems. It is called a "singleton design pattern", look it up for more information.
@@filipe_lopes It is a hard generic question to be answered in one youtube comment. If you are making your first game with a couple of scenes and scripts, you are fine with it. When you start feeling friction and increasing commitment to it, you are mature enough to google for different way how to solve your problem without using statics. Is it understandable at least a bit? :-)
Live it, it's so detailed and I haven't seen any other tutorial like this. I had no idea why you would even need events, but now I think they are the most useful thing and I going to start learning them
I swear to GOD! I used unity for 3 years without using events (I just had references for everything I wanted to access), but I recently took the plunge and learned them & their workflow, And they're sooo useful.
That was the slickest way I've ever heard for telling me to subscribe. Absolutely brilliant! Also great tutorial, I'll definitely be referencing this at a later date when I'm ready to tackle this in my own projects.
THANK YOU!! this has helped so much, it was one of those thing that i’ve been struggling to understand for so long and this is the only video that actually explained it in a way that makes everything make sense
I swear the RUclips algorithm can see into the future. I had some issues with stuff I was doing for a project so I approached one of my teachers, he didn't have a lot of time at that moment, but he explained me some things and told me I should look into events. This video was recommended to me a few weeks prior to that conversation...
This is called the pub/sub pattern. It's only one of many, many ways to do message passing in OOP, and definitely not the end-all be all. The pro is it's simple, but the cons are it's relatively slow and very difficult to scale without major maintainability costs. Great for small projects!
Because almost every tutorial creator is a beginner themself who spews regurgitated content and has no computer science background or a subject matter expert level experience in Unity. They know that the beginner stage gets the most views, so they are content with showing people how to make a sprite jump and collide and maybe update some text on the screen. 90% of people will quit after that point, so why try hard for 10% viewer retention.
I cant thank you enough for this tutorial , everywhere I see is only beginner tutorial , it was something I really needed as intermediate programmer , also if u can suggest some more like these not the beginner ones , which are essential for unity.
@@ChanDawg86 More like it took me years to discover and start practically using them. I'm self-taught, so I would come up with duck tape solutions and stubbornly stick to them because a solution is a solution, right? I now know that the answer to that is no lol I even came up with my own janky version of the Singleton pattern that didn't use the static keyword.
While the singleton pattern is an easy way to reference other objects it is considered an 'anti-pattern'. This is because it violates some key design principles and makes changes down the line harder to implement. Other design patterns which are a bit more complex to understand and implement but once implemented they can make things so much easier and safer down the track. If you are interested have a look into the Dependency Injection (DI) pattern, once setup it can be amazing. Remember, depending on the project, some patterns are better than others. This pattern may be fine for small projects.
There is absolutely nothing wrong with the singleton pattern, people keep repeating this myth over and over but it is just false. As I have become more experienced, I have only been using *more* singletons than before. Singletons CAN be misused, but they are not inherently bad. It makes way more sense in some scenarios to have singletons than have to connect every class to every other class and deal with dependency hell.
I like to use interfaces for this pattern. Then you have control over which type of collection the callbacks are stored in (event is always basically a list), and you can add modular logic as needed. For example you may decide you want to store the balls in some specific order - you could then just add an Order property to the interface and use it as needed.
For every beginners watching this video, please don't take it as a good practice (I mean it). This is actually the opposite, and you should absolutely avoid to program like this. Let me explain a bit more : Singleton design pattern (ensuring that a class has a single instance, and providing a global access point to this instance ) is what the creator wants to show you. First, the singleton pattern is not correctly designed, and doing like it's done in the video can lead to errors. Exposing global variables like that, accessible everywhere in the code, is of course the easiest (read : laziest) way to make components communicate. The biggest issue with that, is the control flow of your application. In the example that is shown in the video, it is all fun and games, everything works properly, because it is a super simple example, with a manager and a ball. Let's say you want to create a big project, with NPCs, World Building, Quest system, inventory etc etc ... If you design your application like this, it means that every system you create, has the possibility to communicate with every other systems of the application. As the project will grow, this will (100%) lead to systems that should have no connection whatsoever communicating together, and therefore, create an absolute undebuggable / unscalable project. The way to go, is first to read actual real books or articles about software design before going to youtube for some obscure tutorials. Advice number one, and probably the most important : learn the SOLID principles , apply it whenever you can. Learn about inversion of control, read articles about design patterns that are ACTUALLY real scalable, good practices. Of course it seems harder, but if you really want to progress, and make real projects, this is the only way to go. And basically, every "problems" that the creator thinks he is solving by using a singleton are actually only problems when you don't know how to handle them (this is no criticism, just a fact). First example : when he says "If you have a lot of balls that you want to communicate, it is tedious to assign them in the editor manually". Solution : Create a serialized array of balls. You can then select them all in the editor, and drag and drop directly to the ball manager script. Second : When he says "If the manager instantiates a ball, he won't be able to communicate with it" : Wrong ! Create a prefab of the ball, with the script Ball attached on it , and do like this in the manager : [SerializeField] private Ball ballPrefab; void OnEnable() { Ball ball = Instantiate(ballPrefab); ball.DoSomething(); } It is as simple as that. If you want to create multiple balls, iterate through an array of the size you want, and instantiate the number of balls you want (and it is actually not even the best way to do that, a pooling system is better to avoid garbage collection overhead, but this is another topic). If you want to keep a reference to the balls in the scene, create a list at the top of the class, and add the balls that you instantiated to this list. I hope this will help a poor soul seeking for answer about unity, which is of course a big, complex topic ! But please, don't take advices like this, this is bad practice. Read before youtube ;)
lol. I liked the video, then read the caption about taking a shot every time you said ball.... and I was sold on subscribing. That is the solid comedy.
I may be talking crazy. But what about having a static dictionary holding references and use an interface that gives an int that is their ID. Then if you have a Terraria tile map for example. Any object with the interface has the tile call it and grab it's ID. Then, if you want to change the objects in that tile. Grab the tile's list of IDs, and just grab the objects from the static dictionary. This way you never have to bother with lots of data and just start with a simply int. Then any additional work with that ID's object can be allocated to either a coroutine or async.
Not gonna lie I didn't realize there was a ball counter throughout the video and I actually spent time counting how many times you said the word ball and I counted 59 which is only one off from the actual number, ngl kinda impressed with how close I got lol
I would suggest instead of using static fields, perhaps consider some architectural patrerns (like MVVM, MVC, …). But please note I am new to unity/game dev and I am comming from field of mobile apps dev, therefore this might be just me seeing issue from that perspective (and not understanding fully). I would love to hear from collegues in game dev field what are common patterns and architecture for managing events, or other styles of communication in unity projects. Please let me know :).
Static instances can be very useful if you only ever want to have one object of a given type active, it's called the singleton design pattern, and I use it all the time, however something to be aware of is that static variables persist between scenes and if you load a new scene without an instance of that type and a script tries to access it it will return null since that particular object instance doesn't exist anymore. I also like to set it up so any instance of that class that is created after the Instance field has been assigned is destroyed, this isn't necessary but it does give you one less way to accidentally break your code. Here's how I tend to write singletons when coding for Unity projects: private static MyClass instance; public static MyClass Instance { get{ return instance: } } private void Awake() { if(instance != null && instance != this) { Destroy (this.gameObject); } else instance = this; } Something to note is that I set this in awake so you need to get it in Start or later.
I think I watched this video a year ago, and I didn’t understand it at all. Recently I’ve been working on a lite RTS game with 100s of different objects, systems, managers. I have actually been using this exact pattern and it works so well! It gets really powerful if you make a scriptable object for the balls. Then each can have specific properties and data you can either pass through the event or reference for very precise control.
I just learned something about System dot serializable scripts. I made a bunch of Arrays and scripted with foreach. Im happy to have Arrays now so I can just put New objects in the inspector instead of Scripting each one. I made a spawner with 10 waves of enemies with over 900 likes of always repeating Code. Now I wave 170 lines doing more stuff than before and with unlimited waves. Once you notice sich thing you can work with another Perspective on these things. I love to see the progress in learning
Lovely tutorial, very clear and high quality. The only issue though is that you are showing a practice that becomes quicky problematic without mentioning it. Why is it problematic ? - Singleton causes spaghetti code and quickly make classes impossible to use outside of a particular context ( create dependencies). It's a good pattern to start, but I would advice to look for other patterns as well to have more solutions in your toolbox (useful ones are scriptable object architecture or Dependency injections for example). Feel free to check out my tutorial about scriptable object architecture if you are interested in original way to pass data in Unity. Also, instead of having the static events in the BallManager you could try a new static GameEvent class. This way you have one location for all your events (you can even make categories) and classes subscribing to those events are decoupled from a specific class but coupled to the bridge : GameEvents. Granted, in your example there is not much going on, but in a bigger game in might be useful. Continue the good videos 👍
Thanks very much! Yeah I tend to keep my events in a static event class since I think it's cleaner to keep them all in one place rather than in disparate scripts
dude he's literally just showing you how he built up to usinng Events. We all know Static classes are Bad, you aren't some genius comoing over here to tell us something we don't know.
No we don't all know it, matter of fact its still very used everywhere. Most tutorials use it ^^. I never said I was a genius, I just commented on his video. Also, I never said they were bad, I just mention that a Singleton can create unwanted dependencies.
You don't advertise on someone else's channel. Especially when your content is so bad. SOAP is WAY more coupled than a global event manager. Get out of here. Reported for advertising on other channels.
@@newf_gg1230 I see, yeah maybe I should not have suggested my channel. I was merely trying to guide to other solutions and I know, by experience that SO architecture works well for decoupling. I am not sure I understand why you would say its way more coupled. Curious to know your stance and where that comes from.
Correct my if I'm wrong but at 6:56, shouldn't you subscribe to the event in the start method? Cross reference another class in the awake method can be tricky because you'll end up in a race condition. With subscribing in the Start method we make sure that BallManager is 100% initialized before Ball.
You can register the ball to an array on the ball manager and it will do the same without using events . I believe events eill be tougher on memory than this method
May be for this simple example yes. However events are extremely powerful is programming, not just in game development. Once you have a complex project event becomes a life saver.
Great video with Good Style ... but many "specialist" can't understand the main idea of this video and begin discussion which "singleton design pattern" must be use and why static fields isn't good :))
Yeahhh I really didn't expect people to focus so hard on singletons... I only intended to mention it in passing but I stepped into a bit of a minefield lol. Guess I know for next time
Static means that there is only one. In the case of a class, it means you don't make instances. So for example, if BallManager is static, you can do: BallManager.Foo(); BallManager.Bar(); It'll work just fine. If BallManager wasn't static, you'd need to make an instance like this: BallManager ballManager = new BallManager(); ballManager.Foo(); ballManager.Bar(); See how we make an object and assign it to a variable? Because BallManager isn't static, there can be multiple BallManagers, so we have to make one. For the BallManager class, it makes sense to have it be static because there should only be one Manager. For the Ball class, it makes more sense for it to not be static. There's no reason to limit ourselves to having only one Ball. We use static classes all the time for things that should "just be there" for anything to use. Console is a static class, which we use like Console.WriteLine("Hello World"). We don't need to make a Console object, the Console just exists. Non-static classes are things we want to be able to create instances of, like the objects in our game. It's not a given that there will be any Ball in our scene - there might be none at all, or there might be many of them. A class can also have static fields, like a static string. If we have a static string field on our Ball class, even though the class is non-static, if one Ball changes the string it updates for every ball. So if Ball.Str is static, changing ball1.Str also changes ball2.Str. Even though they're on different instances, because the string is static, they all reference the same string.
@@tomysshadow Very well summarised! The only thing that I would add is that the way static fields work is by assigning the fields to the class object, rather than an instance object of the class. Meaning that any given class inherently has a class object to which static fields and methods are assigned. Therefore, these are also accessible to instances of the class but unlike non-static fields and methods (of which each instance has its own "snapshot"), the static ones are shared between all instances of a class.
Visual Basic refers to static as 'Shared' if that clarifies what static does. it's like everyone sharing one box of pizza (static) instead of having their own boxes of pizza to themselves (non-static).
Started learning a bit of unity recently. Have a background in programming. Was uncertain about how the course I'm watching handle things. Don't like dragging stuff and not seeing it spelled out in the code itself. THANK YOU. (Don't of this will help me with everything I'm not certain about but I suspect it will help somewhat. Again, thank you very much.)
If you have any suggestions about how to "attach stuff to each other" without dragging and dropping, please let me know. Or if it does not make sense for some reason… Thank you again.
Thanks for the video, but the title is a bit clickbaity. A static reference that assures only one instance is living is a Singleton Pattern and the event related architecture is the Observer Pattern. There are other concepts in unity that, in my opinion, are more fundamental than these, like the Composite Pattern, the SOLID principles, the Proptotype pattern (basically how prefabs works). And if you are talking about the Unity Engine itself (not only scripting) there are concepts like scene splitting, prefab utilization and prefab variants, project organization and folder structure that I think is even more important. Singleton is a pattern that works ok in small projects, but can be bad in bigger projects with too many things referencing each other without an abstraction layer and too much static state. Another pattern that is usually compared to singleton for these solutions is the Service Locator. It is usually implemented using interfaces and a static class that keeps references to registered services.
Thanks for sharing. I wasn't sure if C# had something similar to lambda functionality you find in Javascript, but what you're describing is the Publisher/Subscriber module design pattern I've been using in web SaaS applications.
how about arrays or lists? having an array as a static variable and when any ball is instantiated it adds itself to that array so the ball manager can find it there or have the array as a public variable in ballamanager instead of static and do the same thing
You explained the Unity static class and event concepts very clearly. I had trouble understanding the specifics from the Unity chapter alone, but this filled in several gaps. Thank you!
As someone has already said this would’ve been so helpful when I first started learning Unity, hopefully there’s someone in that position right now watching this vid so they don’t have to learn it the hard way. Ps: would you happen to have a discord sever? I looked around but didn’t see anything, I think it would be a great way to build up your community, it’s also good to start when you’re still small so you don’t have to try to push everyone in all at once when you get bigger lol. If you don’t have a discord server I’m more then happy to help you out, I’ve setup multiple professional servers and currently moderate a few of them, let me know if that’s something you’re interested in🙂
So its like a Hearer and Speaker.... (Just Guessing) Where the Hearer is the static BallManager NameInstance; and the Speaker are the event static Action OnEnableBALLS; Hmmm.... so to talk to Statics Objects i "need" a Action On.... ok... theres probably other methods but im guessing this works in most Situations
Great video, I would like to mention GetComponent and FindObjectOfType. These are both extremely useful methods for finding objects with a reference to the object or without. It is also important to note that if for whatever reason you can't use the singleton design pattern (because static instances persist between scenes) you could use FindObjectType to get the object with a manager script on it in order to subscribe to events. You could also just delete the references to specific objects in the OnSceneLoad event. Not going to explain it fully as it would take some time, but look into the unity documentation.
These are expensive. Be sure to cache them and not call GetComponent or FindObjectOfType every frame. Also, in most use cases for this you are creating tighter coupling, so always look for an alternative way. Only use what he recommends if you literally have no other choice imo.
Does C#/Unity allow to find parents/children of a game object or of a scene? (This would be pretty easy, performant and safe in Swift language, for instance)
❤Thank you for your efforts.❤ I would however be driven with care when implementing singletons without the correct use of the pattern. They can become unruly for testing, create strong coupling, and without guard clausing that Instance variable, you may find trouble ahead when your project code complexity grows or you load a new level withouth handling that script refiring and creating another ! Here is an example explaining what I mean and to go forward with: public static Instance {get; private set;} private static instance; void Awake() { if(Instance != null) DestroyImmediate(gameObject); else { Instance = this; instance = Instance; DontDestroyOnLoad(instance.gameObject); } working with instance inside the class and calling Instance from any other scripts :) (: All in all, fo me, this has some really nice overviews of some key operational mechanisms in Unity using C#, looking forward to your upcoming videos :)
Agreed! I chose to omit explaining the singleton pattern for brevity since I only briefly touched on static instances, but perhaps I should've spent some more time explaining the associated pitfalls
@@Archions Bruh, you rule for even doing a YT tutorial, especially one that covers some of the key "get ahead" areas for early entrants, but yeah somethings, like this, can obvs be a bit "trappy" down the line as that complexity grows, so prob best to give em all the ammo you can :) I still say very very well done on a fantastic tutorial that does indeed cover a great deal in short form. Very good indeed and dont you forget it, I'm subbed and look forward to seeing more from you bosscat! let's goooooooooo
The video and the concept on its own is pretty good but the tutorial and the information given is rather questionnable. The conclusion that events are the way to go is perfect though, I'm not saying that's a bad thing to do. However few things to keep in mind. In the first part of the video you show the example of ball1, ball2, ball3 and say it's tedious. If you've ever heard of arrays, you know that this isn't tedious at all. You can have 150 balls on your scene and still drag & drop them into an array, and that doesn't take a lot of time to do. Showing your method in the video kinda implicitly says "it's the only way" where it's definitely not. - When you want to access/modify scripts from other scripts, it's not a matter of accessibility. It's a matter of context. If the object exists when the other object also exists, then a drag & drop is sufficient. If it's not, then there ALWAYS is a context from where these two objects should communicate. Collisions, Instantiation, etc... not all of your objects in your games require a manager and events. There should be some context at some point. - Showing the Singleton pattern when talking about "Balls" is not relevant. A singleton is literally one single instance. Showing that in your video and telling "it's not working" is kinda misleading in my opinion. There is no reasons or logic to use a singleton is that case. - Events shouldn't be named with "On" at the start. They should be named on the actual event that happened. For instance in your case, the event should be called something like "disabledBalls". Only the method that subscribes to that event you start with "On". Think about how Unity works, the methods you use are not "TriggerEnter" it's "OnTriggerEnter" because the event is not OnTriggerEnter, but the method is. - When using Action with parameters, it's important to keep in mind that with just the Action sort of things, it's really hard to see which parameter does what. Try learning about delegates to have names put next to the type to have way more information. The video and its intentions are good, but the way it is shown is not that great. Keep it up though, the editing part and the explanation are pretty cool! Sorry about that long message and I hope you've learned one thing or two!
Hey, thanks for the detailed feedback! It's always challenging trying to strike the right balance between brevity and detail. I didn't want the video to get super long and chose instead to focus on the core concept of communicating between objects in C#. Naturally this comes at the cost of skipping over information which would still be useful. I will keep your feedback in mind when deciding on the balance between detail and engagement in the future !
"Because we can only ever have one static instance for any given class. " That's actually a big mistake here. You can have as many static instances in class as you want with any collection like list or array. To be clear I'm not recommending it. But in the class Ball you can have: public static readonly List Instances = new List(); and instead of: Instance = this; you do: Instances.Add(this); and in OnDestroy you do: Instances.Remove(this); For small and simple project this should be sufficient. But in order to make it a little better. You could make BallManager just a simple MonoBehaviour and in Ball class you just "find it" in awake. So: void Awake() { var ballManager = FindObjectOfType(); ballManager.AddBall(this); } with this you can get rid of this ugly static fields. And with all instances in one place you can count them, iterate them, make Object Pooling, and more.
You don't have to assign them in the editor, you can do that at runtime just fine. Ballmanager can Instantiate balls and keep the references in a List/Array or even as simple children if you choose Ballmanager as their parent. So then you have full control over enabling/disabling them. No need to manually numerate them in the inspector or such.
9:24 There's gotta be a way to modify the parameter of an event in an other way than a field, like in a script, no ? If someone knows, please tell me ? :)
Unity FAILS to provide basic communication methods on an instance level (e.g. for cross-scene/cross (nested) prefab (variants) communication ...) No matter what you use (ScriptableObjectReferences, Events, maybe a (G)UID system) it will still get extremely messy & complex when you communicate on an instance level (and not just sending from instance to a singleton/static which is the easiest scenario)
Kinda backwards. The balls shouldn't know about the manager at all, as they are at a lower level. So the events should be on the ball side. Because the balls get a dependency now. Imagine you want to replace the manager, now you have to modify the ball code as well.
Few possibilities: 1. Make sure your static class is in your game scene (i.e. the script is on a game object) and the object is enabled 2. Make sure you're assigning the instance in the Awake function (Instance = this) 3. Make sure that wherever you're referencing the static class from, is doing so AFTER the instance is set. I.e. if (in your static class) you're assigning the reference in the Awake function, consider referencing it in any function except the Awake function in other scripts. If you try to reference your static instance from other classes on their Awake it will cause errors if their awake is run before the awake function in the static class. Hope that makes sense
Nice introduction to events but as the others said i dont think you have the expertise to be making this types of videos (yet) In a real game, id assume you would have those balls inside a list/array or other datastructure, so you could just inject that into the ball manager, much easier to understand and cleaner. Events are fun but i think they are more useful when used by SYSTEMS to communicate with other systems. For example, having "physicsManager" inform "ballManager" of a collision or something, since you dont want those 2 systems (or 3, 4 or 1000, plenty of systems would want to be modified about collision) to know about /depend on each other :)
I prefer to have a list on the manager / single instance. See ~code below: public class Ballmanager : MonoBehaviour { public static Ballmanager Instance; public List Balls; void Awake() { Instance = this; } void DisableBalls() { foreach (var ball in balls) { ball.gameObject.setActive(false) } } } public class Ball : MonoBehaviour { void OnEnable() { if(!Ballmanager.Instance.Balls.Contains(this)) Ballmanager.Instance.Balls.Add(this); } void OnDisable() { if(Ballmanager.Instance.Balls.Contains(this)) Ballmanager.Instance.Balls.Remove(this); } }
Grats on your list. Now update the UI to add to a score. Now update your achievement system. Now update your stats. Now update your character state. Is it game over? Have you ran out of balls? Oh right, you're not firing an event to let any scripts that MIGHT want to know about the balls number changing. Guess you better hard code and tightly couple this then. Please don't teach bad habits. Your list is fine, but it's irrelevant to what he's showcasing which is communication and decoupling.
@@newf_gg1230 No need to be condescending. When you mature you will learn that there is no right or wrong, only problem solved or not. The problem was how to reference objects without manually doing it with a serialized reference. A simple List.Add in OnEnable solves that. Having UI components poll a manager is not a bad practice. It's a different practice.
Hey everyone, it's only an anti-pattern if you are following OO and SOLID. Specifically, it couples things together using global state, hides dependencies, can lead to concurrency issues if you are not careful, and can hurt some forms of testability. HOWEVER, there are very successful programs/programmers that do not follow OO/SOLID. Remember that OO is a *constraint* because *limits* what you can code (which is good thing for some people... it's the tradeoff they make). Anyhow, it's all relative to what you are trying to achieve and where your programming practice is at and who you are working with/for.
BROOOO!!! This literally describes what I've banged my head on my desk trying to figure out for weeks. THANK YOU!
Happy to hear it my dude
Bro I love this. I have been trying to find a way to do this and no other tutorial has been this instructive
Glad to hear it my guy
I've been searching for this video for so long. The perfect explanation that tied all of my entry level programming knowledge together in a nice bow. Thank you so much !!
Be careful about the static fields. They are preserved between level loads which may cause problems.
It is called a "singleton design pattern", look it up for more information.
Its an "anti pattern" not a design pattern :)
@@killereks Well it is a design pattern, standardizing solving very specific problems. It may be used badly, just as any other design pattern.
Interesting. Do you know how one could avoid those problems while still enjoying the "static" benefit?
global state cringe
@@filipe_lopes It is a hard generic question to be answered in one youtube comment. If you are making your first game with a couple of scenes and scripts, you are fine with it. When you start feeling friction and increasing commitment to it, you are mature enough to google for different way how to solve your problem without using statics.
Is it understandable at least a bit? :-)
im rewatching this video later and copying it down
thank for your work sir
Live it, it's so detailed and I haven't seen any other tutorial like this. I had no idea why you would even need events, but now I think they are the most useful thing and I going to start learning them
No wonder Godot made event signals part of the basic tutorial
I swear to GOD! I used unity for 3 years without using events (I just had references for everything I wanted to access), but I recently took the plunge and learned them & their workflow, And they're sooo useful.
That was the slickest way I've ever heard for telling me to subscribe. Absolutely brilliant! Also great tutorial, I'll definitely be referencing this at a later date when I'm ready to tackle this in my own projects.
Glad to hear it, good luck!
Awesome video! When I learned about design patterns my coding life changed forever.
Btw the ball counter zooming in at the end was the perfect ending
Hmm these balls gave me nut clarity about programming. You have good sense of balls. Bravo!
THANK YOU!! this has helped so much, it was one of those thing that i’ve been struggling to understand for so long and this is the only video that actually explained it in a way that makes everything make sense
I swear the RUclips algorithm can see into the future. I had some issues with stuff I was doing for a project so I approached one of my teachers, he didn't have a lot of time at that moment, but he explained me some things and told me I should look into events. This video was recommended to me a few weeks prior to that conversation...
Literally went over all of this today and this video just reconfirmed I really did get what I learned. Thanks
This is called the pub/sub pattern. It's only one of many, many ways to do message passing in OOP, and definitely not the end-all be all. The pro is it's simple, but the cons are it's relatively slow and very difficult to scale without major maintainability costs. Great for small projects!
Wrong on all accounts except that it isn't the only way to pass messages. That's a 1 for 4. Not bad.
I've seen good tutorials in the past.
This was a game changer for me.
Thank you.
Simplest and Easiest way to learn about event, Loved your video. Keep up the good work bro.
I loved the simple explanations, and the trial and error of why one concept won't work and how to resolve the issues has been insightful! thnx!
This is actually such important information. I don't understand why these concepts aren't preached more to beginners
Because almost every tutorial creator is a beginner themself who spews regurgitated content and has no computer science background or a subject matter expert level experience in Unity. They know that the beginner stage gets the most views, so they are content with showing people how to make a sprite jump and collide and maybe update some text on the screen. 90% of people will quit after that point, so why try hard for 10% viewer retention.
@@newf_gg1230 valid response
This video was awesome: it's great content, great presentation, and even better balls.
Glad to hear it!
This video got balls.;;
This video was pretty awesome. Have heard of events before but i didn't know that they were so useful
Yup, they are incredibly helpful and I pretty much use them in all my games
I cant thank you enough for this tutorial , everywhere I see is only beginner tutorial , it was something I really needed as intermediate programmer , also if u can suggest some more like these not the beginner ones , which are essential for unity.
This video would've been incredibly helpful when I was learning Unity! It perfectly describes concepts that took me years to figure out on my own!
took you years to figure out events? jesus christ
@@ChanDawg86 More like it took me years to discover and start practically using them. I'm self-taught, so I would come up with duck tape solutions and stubbornly stick to them because a solution is a solution, right? I now know that the answer to that is no lol
I even came up with my own janky version of the Singleton pattern that didn't use the static keyword.
So clear and to the point, thank you!
You could have a list of balls in the ball manager, which a ball adds itself to when created. The event system is definitely better though
That's a lot of balls.
Yep, a register observer and unregister observer method. Good for loosely coupled objects working in a closed context
the ball counter was pure genius
While the singleton pattern is an easy way to reference other objects it is considered an 'anti-pattern'. This is because it violates some key design principles and makes changes down the line harder to implement. Other design patterns which are a bit more complex to understand and implement but once implemented they can make things so much easier and safer down the track.
If you are interested have a look into the Dependency Injection (DI) pattern, once setup it can be amazing.
Remember, depending on the project, some patterns are better than others. This pattern may be fine for small projects.
Fully agree, dependency injection is a great way to handle referencing other objects
@@Archions It is definitely not a beginner friendly topic though and a beginner might not understand or be able to appreciate the pros/cons of DI.
There is absolutely nothing wrong with the singleton pattern, people keep repeating this myth over and over but it is just false. As I have become more experienced, I have only been using *more* singletons than before.
Singletons CAN be misused, but they are not inherently bad. It makes way more sense in some scenarios to have singletons than have to connect every class to every other class and deal with dependency hell.
Balls
I like to use interfaces for this pattern. Then you have control over which type of collection the callbacks are stored in (event is always basically a list), and you can add modular logic as needed. For example you may decide you want to store the balls in some specific order - you could then just add an Order property to the interface and use it as needed.
Legends say that the ball counter is still going up
Subbed. Hope to see more unity tutorials like this.
Thanks! I'll see what I can do
For every beginners watching this video, please don't take it as a good practice (I mean it). This is actually the opposite, and you should absolutely avoid to program like this.
Let me explain a bit more :
Singleton design pattern (ensuring that a class has a single instance, and providing a global access point to this instance ) is what the creator wants to show you. First, the singleton pattern is not correctly designed, and doing like it's done in the video can lead to errors.
Exposing global variables like that, accessible everywhere in the code, is of course the easiest (read : laziest) way to make components communicate. The biggest issue with that, is the control flow of your application. In the example that is shown in the video, it is all fun and games, everything works properly, because it is a super simple example, with a manager and a ball.
Let's say you want to create a big project, with NPCs, World Building, Quest system, inventory etc etc ... If you design your application like this, it means that every system you create, has the possibility to communicate with every other systems of the application. As the project will grow, this will (100%) lead to systems that should have no connection whatsoever communicating together, and therefore, create an absolute undebuggable / unscalable project.
The way to go, is first to read actual real books or articles about software design before going to youtube for some obscure tutorials. Advice number one, and probably the most important : learn the SOLID principles , apply it whenever you can. Learn about inversion of control, read articles about design patterns that are ACTUALLY real scalable, good practices. Of course it seems harder, but if you really want to progress, and make real projects, this is the only way to go.
And basically, every "problems" that the creator thinks he is solving by using a singleton are actually only problems when you don't know how to handle them (this is no criticism, just a fact).
First example : when he says "If you have a lot of balls that you want to communicate, it is tedious to assign them in the editor manually". Solution : Create a serialized array of balls. You can then select them all in the editor, and drag and drop directly to the ball manager script.
Second : When he says "If the manager instantiates a ball, he won't be able to communicate with it" : Wrong !
Create a prefab of the ball, with the script Ball attached on it , and do like this in the manager :
[SerializeField] private Ball ballPrefab;
void OnEnable()
{
Ball ball = Instantiate(ballPrefab);
ball.DoSomething();
}
It is as simple as that. If you want to create multiple balls, iterate through an array of the size you want, and instantiate the number of balls you want (and it is actually not even the best way to do that, a pooling system is better to avoid garbage collection overhead, but this is another topic).
If you want to keep a reference to the balls in the scene, create a list at the top of the class, and add the balls that you instantiated to this list.
I hope this will help a poor soul seeking for answer about unity, which is of course a big, complex topic !
But please, don't take advices like this, this is bad practice. Read before youtube ;)
lol. I liked the video, then read the caption about taking a shot every time you said ball.... and I was sold on subscribing. That is the solid comedy.
Events, Actions and lamdas have made my life so much easier :)
your voice is like a news speaker explaining a tragedy with 30 deaths, it feels weird to watch the video
I may be talking crazy. But what about having a static dictionary holding references and use an interface that gives an int that is their ID.
Then if you have a Terraria tile map for example. Any object with the interface has the tile call it and grab it's ID.
Then, if you want to change the objects in that tile. Grab the tile's list of IDs, and just grab the objects from the static dictionary.
This way you never have to bother with lots of data and just start with a simply int. Then any additional work with that ID's object can be allocated to either a coroutine or async.
3:14 This kind of static instance is called the Singleton Pattern, in case you need to look it up
Really?
This is pretty different from what I use Singletons for
I'm ur 56th subscriber, Thank for the tutorial.
Not gonna lie I didn't realize there was a ball counter throughout the video and I actually spent time counting how many times you said the word ball and I counted 59 which is only one off from the actual number, ngl kinda impressed with how close I got lol
I would suggest instead of using static fields, perhaps consider some architectural patrerns (like MVVM, MVC, …). But please note I am new to unity/game dev and I am comming from field of mobile apps dev, therefore this might be just me seeing issue from that perspective (and not understanding fully). I would love to hear from collegues in game dev field what are common patterns and architecture for managing events, or other styles of communication in unity projects. Please let me know :).
Static instances can be very useful if you only ever want to have one object of a given type active, it's called the singleton design pattern, and I use it all the time, however something to be aware of is that static variables persist between scenes and if you load a new scene without an instance of that type and a script tries to access it it will return null since that particular object instance doesn't exist anymore. I also like to set it up so any instance of that class that is created after the Instance field has been assigned is destroyed, this isn't necessary but it does give you one less way to accidentally break your code.
Here's how I tend to write singletons when coding for Unity projects:
private static MyClass instance;
public static MyClass Instance {
get{
return instance:
}
}
private void Awake() {
if(instance != null && instance != this) {
Destroy (this.gameObject);
}
else instance = this;
}
Something to note is that I set this in awake so you need to get it in Start or later.
Great info, usually I use lists, but this is great when you want to keep iteration down.
I think I watched this video a year ago, and I didn’t understand it at all. Recently I’ve been working on a lite RTS game with 100s of different objects, systems, managers. I have actually been using this exact pattern and it works so well!
It gets really powerful if you make a scriptable object for the balls. Then each can have specific properties and data you can either pass through the event or reference for very precise control.
I just learned something about System dot serializable scripts. I made a bunch of Arrays and scripted with foreach. Im happy to have Arrays now so I can just put New objects in the inspector instead of Scripting each one. I made a spawner with 10 waves of enemies with over 900 likes of always repeating Code. Now I wave 170 lines doing more stuff than before and with unlimited waves. Once you notice sich thing you can work with another Perspective on these things. I love to see the progress in learning
Great, detailed video! Keep up the good work!
00:15 ECS : "Hold my ISystem"
It is important for a manager to communicate correctly with their balls
Lovely tutorial, very clear and high quality. The only issue though is that you are showing a practice that becomes quicky problematic without mentioning it.
Why is it problematic ?
- Singleton causes spaghetti code and quickly make classes impossible to use outside of a particular context ( create dependencies).
It's a good pattern to start, but I would advice to look for other patterns as well to have more solutions in your toolbox (useful ones are scriptable object architecture or Dependency injections for example). Feel free to check out my tutorial about scriptable object architecture if you are interested in original way to pass data in Unity.
Also, instead of having the static events in the BallManager you could try a new static GameEvent class. This way you have one location for all your events (you can even make categories) and classes subscribing to those events are decoupled from a specific class but coupled to the bridge : GameEvents. Granted, in your example there is not much going on, but in a bigger game in might be useful. Continue the good videos 👍
Thanks very much! Yeah I tend to keep my events in a static event class since I think it's cleaner to keep them all in one place rather than in disparate scripts
dude he's literally just showing you how he built up to usinng Events. We all know Static classes are Bad, you aren't some genius comoing over here to tell us something we don't know.
No we don't all know it, matter of fact its still very used everywhere. Most tutorials use it ^^. I never said I was a genius, I just commented on his video. Also, I never said they were bad, I just mention that a Singleton can create unwanted dependencies.
You don't advertise on someone else's channel. Especially when your content is so bad. SOAP is WAY more coupled than a global event manager. Get out of here. Reported for advertising on other channels.
@@newf_gg1230 I see, yeah maybe I should not have suggested my channel. I was merely trying to guide to other solutions and I know, by experience that SO architecture works well for decoupling. I am not sure I understand why you would say its way more coupled. Curious to know your stance and where that comes from.
Correct my if I'm wrong but at 6:56, shouldn't you subscribe to the event in the start method? Cross reference another class in the awake method can be tricky because you'll end up in a race condition. With subscribing in the Start method we make sure that BallManager is 100% initialized before Ball.
This video is gold! It solved my problems
i like the ball counter
You can register the ball to an array on the ball manager and it will do the same without using events . I believe events eill be tougher on memory than this method
May be for this simple example yes. However events are extremely powerful is programming, not just in game development. Once you have a complex project event becomes a life saver.
I'm a 50th subscriber :)
this was very, very informative
Great video with Good Style ... but many "specialist" can't understand the main idea of this video and begin discussion which "singleton design pattern" must be use and why static fields isn't good :))
Yeahhh I really didn't expect people to focus so hard on singletons... I only intended to mention it in passing but I stepped into a bit of a minefield lol. Guess I know for next time
This was helpful af. If only I understand the concept of static 😂
Static means that there is only one. In the case of a class, it means you don't make instances. So for example, if BallManager is static, you can do:
BallManager.Foo();
BallManager.Bar();
It'll work just fine. If BallManager wasn't static, you'd need to make an instance like this:
BallManager ballManager = new BallManager();
ballManager.Foo();
ballManager.Bar();
See how we make an object and assign it to a variable? Because BallManager isn't static, there can be multiple BallManagers, so we have to make one.
For the BallManager class, it makes sense to have it be static because there should only be one Manager. For the Ball class, it makes more sense for it to not be static. There's no reason to limit ourselves to having only one Ball.
We use static classes all the time for things that should "just be there" for anything to use. Console is a static class, which we use like Console.WriteLine("Hello World"). We don't need to make a Console object, the Console just exists. Non-static classes are things we want to be able to create instances of, like the objects in our game. It's not a given that there will be any Ball in our scene - there might be none at all, or there might be many of them.
A class can also have static fields, like a static string. If we have a static string field on our Ball class, even though the class is non-static, if one Ball changes the string it updates for every ball. So if Ball.Str is static, changing ball1.Str also changes ball2.Str. Even though they're on different instances, because the string is static, they all reference the same string.
@@tomysshadow Very well summarised!
The only thing that I would add is that the way static fields work is by assigning the fields to the class object, rather than an instance object of the class.
Meaning that any given class inherently has a class object to which static fields and methods are assigned. Therefore, these are also accessible to instances of the class but unlike non-static fields and methods (of which each instance has its own "snapshot"), the static ones are shared between all instances of a class.
Visual Basic refers to static as 'Shared' if that clarifies what static does. it's like everyone sharing one box of pizza (static) instead of having their own boxes of pizza to themselves (non-static).
I literally just figured this out last week where was this video then
You sound like james jani so much . Thanks for the video
Thank you for this! I actually learned something new and helpful :D
Well explained, thanks
Thanks a lot man this was very useful!
Started learning a bit of unity recently. Have a background in programming. Was uncertain about how the course I'm watching handle things. Don't like dragging stuff and not seeing it spelled out in the code itself. THANK YOU. (Don't of this will help me with everything I'm not certain about but I suspect it will help somewhat. Again, thank you very much.)
If you have any suggestions about how to "attach stuff to each other" without dragging and dropping, please let me know. Or if it does not make sense for some reason… Thank you again.
ruclips.net/video/dtv7mjj_iog/видео.html - here's a great video about some ways you can reference objects in Unity/C#
@@Archions Thank you!
Thanks for the video, but the title is a bit clickbaity. A static reference that assures only one instance is living is a Singleton Pattern and the event related architecture is the Observer Pattern.
There are other concepts in unity that, in my opinion, are more fundamental than these, like the Composite Pattern, the SOLID principles, the Proptotype pattern (basically how prefabs works). And if you are talking about the Unity Engine itself (not only scripting) there are concepts like scene splitting, prefab utilization and prefab variants, project organization and folder structure that I think is even more important.
Singleton is a pattern that works ok in small projects, but can be bad in bigger projects with too many things referencing each other without an abstraction layer and too much static state. Another pattern that is usually compared to singleton for these solutions is the Service Locator. It is usually implemented using interfaces and a static class that keeps references to registered services.
fk my brain hurt...when i heard object orientate but i appreciate the 10 min vid to tackle my main issue
Thanks for sharing. I wasn't sure if C# had something similar to lambda functionality you find in Javascript, but what you're describing is the Publisher/Subscriber module design pattern I've been using in web SaaS applications.
Very nice, check out the 'Observer pattern' in C# - I think that's the equivalent of the Publisher/Subscriber design pattern in JS
Delegates are the closest C# equivalent to anonymous functions.
I love ur videos ❤❤
Very underrated, keep it up!
Thanks, will do!
I love object oriented programming
how about arrays or lists? having an array as a static variable and when any ball is instantiated it adds itself to that array so the ball manager can find it there
or have the array as a public variable in ballamanager instead of static and do the same thing
awesome vids.
You explained the Unity static class and event concepts very clearly. I had trouble understanding the specifics from the Unity chapter alone, but this filled in several gaps. Thank you!
Very calming and useful information , oh and i expected the balls count to go upto 69 :P
Lmao if only
As someone has already said this would’ve been so helpful when I first started learning Unity, hopefully there’s someone in that position right now watching this vid so they don’t have to learn it the hard way.
Ps: would you happen to have a discord sever? I looked around but didn’t see anything, I think it would be a great way to build up your community, it’s also good to start when you’re still small so you don’t have to try to push everyone in all at once when you get bigger lol. If you don’t have a discord server I’m more then happy to help you out, I’ve setup multiple professional servers and currently moderate a few of them, let me know if that’s something you’re interested in🙂
Sure, sounds like a good idea - what's your Discord? (Feel free to email me it if you don't want to post it publicly lmao)
@@Archions That's awesome to hear, I don't mind posting it here, it's @LegendarySwordsman2#7777, can't wait to get started.
discord.gg/T6ZgeKW6 esketit
So its like a Hearer and Speaker....
(Just Guessing) Where the Hearer is the static BallManager NameInstance;
and the Speaker are the event static Action OnEnableBALLS;
Hmmm.... so to talk to Statics Objects i "need" a Action On.... ok... theres probably other methods but im guessing this works in most Situations
Thanks mate!
Great video, I would like to mention GetComponent and FindObjectOfType. These are both extremely useful methods for finding objects with a reference to the object or without. It is also important to note that if for whatever reason you can't use the singleton design pattern (because static instances persist between scenes) you could use FindObjectType to get the object with a manager script on it in order to subscribe to events. You could also just delete the references to specific objects in the OnSceneLoad event. Not going to explain it fully as it would take some time, but look into the unity documentation.
These are expensive. Be sure to cache them and not call GetComponent or FindObjectOfType every frame. Also, in most use cases for this you are creating tighter coupling, so always look for an alternative way. Only use what he recommends if you literally have no other choice imo.
Thank you so much!
Does C#/Unity allow to find parents/children of a game object or of a scene? (This would be pretty easy, performant and safe in Swift language, for instance)
❤Thank you for your efforts.❤ I would however be driven with care when implementing singletons without the correct use of the pattern. They can become unruly for testing, create strong coupling, and without guard clausing that Instance variable, you may find trouble ahead when your project code complexity grows or you load a new level withouth handling that script refiring and creating another !
Here is an example explaining what I mean and to go forward with:
public static Instance {get; private set;}
private static instance;
void Awake() {
if(Instance != null)
DestroyImmediate(gameObject);
else {
Instance = this;
instance = Instance;
DontDestroyOnLoad(instance.gameObject);
}
working with instance inside the class and calling Instance from any other scripts :)
(: All in all, fo me, this has some really nice overviews of some key operational mechanisms in Unity using C#, looking forward to your upcoming videos :)
Agreed! I chose to omit explaining the singleton pattern for brevity since I only briefly touched on static instances, but perhaps I should've spent some more time explaining the associated pitfalls
@@Archions Bruh, you rule for even doing a YT tutorial, especially one that covers some of the key "get ahead" areas for early entrants, but yeah somethings, like this, can obvs be a bit "trappy" down the line as that complexity grows, so prob best to give em all the ammo you can :) I still say very very well done on a fantastic tutorial that does indeed cover a great deal in short form. Very good indeed and dont you forget it, I'm subbed and look forward to seeing more from you bosscat! let's goooooooooo
The video and the concept on its own is pretty good but the tutorial and the information given is rather questionnable. The conclusion that events are the way to go is perfect though, I'm not saying that's a bad thing to do.
However few things to keep in mind. In the first part of the video you show the example of ball1, ball2, ball3 and say it's tedious. If you've ever heard of arrays, you know that this isn't tedious at all. You can have 150 balls on your scene and still drag & drop them into an array, and that doesn't take a lot of time to do. Showing your method in the video kinda implicitly says "it's the only way" where it's definitely not.
- When you want to access/modify scripts from other scripts, it's not a matter of accessibility. It's a matter of context. If the object exists when the other object also exists, then a drag & drop is sufficient. If it's not, then there ALWAYS is a context from where these two objects should communicate. Collisions, Instantiation, etc... not all of your objects in your games require a manager and events. There should be some context at some point.
- Showing the Singleton pattern when talking about "Balls" is not relevant. A singleton is literally one single instance. Showing that in your video and telling "it's not working" is kinda misleading in my opinion. There is no reasons or logic to use a singleton is that case.
- Events shouldn't be named with "On" at the start. They should be named on the actual event that happened. For instance in your case, the event should be called something like "disabledBalls". Only the method that subscribes to that event you start with "On". Think about how Unity works, the methods you use are not "TriggerEnter" it's "OnTriggerEnter" because the event is not OnTriggerEnter, but the method is.
- When using Action with parameters, it's important to keep in mind that with just the Action sort of things, it's really hard to see which parameter does what. Try learning about delegates to have names put next to the type to have way more information.
The video and its intentions are good, but the way it is shown is not that great. Keep it up though, the editing part and the explanation are pretty cool! Sorry about that long message and I hope you've learned one thing or two!
Hey, thanks for the detailed feedback! It's always challenging trying to strike the right balance between brevity and detail. I didn't want the video to get super long and chose instead to focus on the core concept of communicating between objects in C#. Naturally this comes at the cost of skipping over information which would still be useful. I will keep your feedback in mind when deciding on the balance between detail and engagement in the future !
"Because we can only ever have one static instance for any given class. "
That's actually a big mistake here.
You can have as many static instances in class as you want with any collection like list or array.
To be clear I'm not recommending it.
But in the class Ball you can have:
public static readonly List Instances = new List();
and instead of:
Instance = this;
you do:
Instances.Add(this);
and in OnDestroy you do:
Instances.Remove(this);
For small and simple project this should be sufficient.
But in order to make it a little better. You could make BallManager just a simple MonoBehaviour and in Ball class you just "find it" in awake. So:
void Awake() {
var ballManager = FindObjectOfType();
ballManager.AddBall(this);
}
with this you can get rid of this ugly static fields.
And with all instances in one place you can count them, iterate them, make Object Pooling, and more.
You don't have to assign them in the editor, you can do that at runtime just fine. Ballmanager can Instantiate balls and keep the references in a List/Array or even as simple children if you choose Ballmanager as their parent. So then you have full control over enabling/disabling them. No need to manually numerate them in the inspector or such.
9:24 There's gotta be a way to modify the parameter of an event in an other way than a field, like in a script, no ? If someone knows, please tell me ? :)
Thanks.
Thanks!
Unity FAILS to provide basic communication methods on an instance level (e.g. for cross-scene/cross (nested) prefab (variants) communication ...)
No matter what you use (ScriptableObjectReferences, Events, maybe a (G)UID system) it will still get extremely messy & complex when you communicate on an instance level (and not just sending from instance to a singleton/static which is the easiest scenario)
Kinda backwards. The balls shouldn't know about the manager at all, as they are at a lower level. So the events should be on the ball side. Because the balls get a dependency now. Imagine you want to replace the manager, now you have to modify the ball code as well.
I thought it was easy to make videogames in Unity!
6:05 Why use Action instead of UnityEvent?
I keep getting Object refrence not set to an instance of an object when trying to refrence a function from the static class?
Few possibilities:
1. Make sure your static class is in your game scene (i.e. the script is on a game object) and the object is enabled
2. Make sure you're assigning the instance in the Awake function (Instance = this)
3. Make sure that wherever you're referencing the static class from, is doing so AFTER the instance is set. I.e. if (in your static class) you're assigning the reference in the Awake function, consider referencing it in any function except the Awake function in other scripts. If you try to reference your static instance from other classes on their Awake it will cause errors if their awake is run before the awake function in the static class.
Hope that makes sense
@@Archions Yeah the mistake was putting the script on an object that is disabled at start up oops, thank you sm for the feedback
Nice introduction to events but as the others said i dont think you have the expertise to be making this types of videos (yet)
In a real game, id assume you would have those balls inside a list/array or other datastructure, so you could just inject that into the ball manager, much easier to understand and cleaner.
Events are fun but i think they are more useful when used by SYSTEMS to communicate with other systems. For example, having "physicsManager" inform "ballManager" of a collision or something, since you dont want those 2 systems (or 3, 4 or 1000, plenty of systems would want to be modified about collision) to know about /depend on each other :)
So freaking helpful!!!
I prefer to have a list on the manager / single instance. See ~code below:
public class Ballmanager : MonoBehaviour
{
public static Ballmanager Instance;
public List Balls;
void Awake()
{
Instance = this;
}
void DisableBalls()
{
foreach (var ball in balls)
{
ball.gameObject.setActive(false)
}
}
}
public class Ball : MonoBehaviour
{
void OnEnable()
{
if(!Ballmanager.Instance.Balls.Contains(this))
Ballmanager.Instance.Balls.Add(this);
}
void OnDisable()
{
if(Ballmanager.Instance.Balls.Contains(this))
Ballmanager.Instance.Balls.Remove(this);
}
}
Grats on your list. Now update the UI to add to a score. Now update your achievement system. Now update your stats. Now update your character state. Is it game over? Have you ran out of balls? Oh right, you're not firing an event to let any scripts that MIGHT want to know about the balls number changing. Guess you better hard code and tightly couple this then. Please don't teach bad habits. Your list is fine, but it's irrelevant to what he's showcasing which is communication and decoupling.
@@newf_gg1230 No need to be condescending. When you mature you will learn that there is no right or wrong, only problem solved or not.
The problem was how to reference objects without manually doing it with a serialized reference. A simple List.Add in OnEnable solves that.
Having UI components poll a manager is not a bad practice. It's a different practice.
This ain't even oop
Is that you como
you can go a whole new level if you make events an ScriptableObject. then you won't have to make the manager class static anymore
Good video about how NOT to write a code.
balls
Hey everyone, it's only an anti-pattern if you are following OO and SOLID. Specifically, it couples things together using global state, hides dependencies, can lead to concurrency issues if you are not careful, and can hurt some forms of testability. HOWEVER, there are very successful programs/programmers that do not follow OO/SOLID. Remember that OO is a *constraint* because *limits* what you can code (which is good thing for some people... it's the tradeoff they make). Anyhow, it's all relative to what you are trying to achieve and where your programming practice is at and who you are working with/for.
Really helpful!
Cool video. But telling beginners to use singletons is a disaster waiting to happen.
All your videos has tightly coupled code and switch statements everywhere, but yea, singletons are the issue here...🤣
You just made my life a whole lot easier🥹