Aside from these, I think the State Pattern was the first proper pattern I learned for game development and it has been soooo helpful in many projects! Definitely recommend that one to people as well
Do you have a recommended resource to learn it. I've learned it but having lots of difficulties while using it so I'm thinking of taking a look at it again.
@@MafiaSniperThere are many resources, the gameprogrammingpatterns site has a good article for it (and other patterns), iHeartGamedev on YT had an easy digestible tutorial for it and I'm sure Jason has mentioned or showed it a couple of times too. I started with an enum to store what the current state is and then just made a switch statement in a single class and put all there, which worked but was a bit rigid and I had a huge file/class. Since then, a State is basically a separate class, which either implements an interface or inherits from an abstract state, and a StateMachine class keeps a dictionary where the key is the state type (can also be an enum, or System.Type directly) and value is of the state interface type (or the abstract state class type if you use that instead). You could also look through the code in existing state pattern assets, like on the asset store or on github for C#/Unity.
i think that "state pattern" is so usefull that it's not even considered as a pattern anymore is just like "the thing" but i agree one of the most powerfull you learn in early journey
@@MafiaSniper Bardent and "iheartgamedev" are good ressource, the longer version is called "finite state machine pattern" but since this comment is very old i think you might have already found a solution.
I use flyweight all the time, but I didn't know it was called that. I use Observer a lot, both for data binding, and for non UI related change events. I use Instance for managers, however, if I can get away with it, I prefer static classes. I do the exact opposite naming for "On" events. I used to do it the way you are, but now I look at it from the point of view of the event calling Invoke. Invoke is the start, and the handler acts "On" the Invoke. Thanks for these videos. Even though I've been programming a very long time, I'm always looking to learn something new.
I still think the clearest naming convention is for invoker to get the "On" and handler to get "handle" added to the name ex OnEventHappened += HandleEventHappened. ...
@@aleksapetrovic7088 The event itself is the action, and the ones registered to that event are acting ON the action. So I might have an event called "ColorChanged", and any object acting on that event would register a method called "OnColorChanged". Technically the ColorChanged event itself isn't changing any colors, it's just notifying objects that are registered to it that a color has changed, and it's passing it along. To me, that means it makes more sense to put the "On" on the method responsible for actually changing the color.
@@aleksapetrovic7088 I already replied, but I think it went into the RUclips black hole. Anyway, it's probably because I edited it a few times in a row. Here's my official cleaned up and well thought out edit of my original :) I see the event itself as the action, and the methods registered to that action as acting ON that action. For example, if I had an event called ColorChanged, the object interested in changing color on that event, would register a method called OnColorChanged.
I have been messing around with Singleton for a while, and finally I understand why people argue about that pattern. Basically, Singleton does exactly the opposite of what other patterns try to do. While other pattern is a little bit complex to keep scripts private, not interacting with other scripts as much as possible to achieve "clean code", Singleton is not only simpler even when comparing with normal coding, it also makes script public and easier for every script to access that script, so it may lead to "dirty code". In my opinion though, while obviously you should keep your code clean, why not make thing much more simpler when you dont need to. If a script fits 2 description that Singleton try to do (can only has 1 instance, and need to expose to everyone), what prevents us from using it? Of course we shouldn't abuse it, but as long as we understand why/when to use it, it shouldn't be a problem.
Clean Code (capital letters) is the main culprit of horrible application performance those days. It's a set of self-imposed "rules" that programmers come up with that only purpose is to make their job easier by sacrificing user experience.
@@SylvanFeanturi I'm sorry that I'm still new to programing, so I may not fully understand what you are trying to say. Yes, I agree that those rules' purpose is to make programmers' job easier, but I dont think any of them has anything to do with performance or user experience, at least from what I have learned. Clean code are just rules to keep code clean, arent they? They are not mean to increase or decrease performance. If the performance is horrible, shouldn't it be the responsibility of the programmers themself for not knowing how to optimize? Once again, if I misunderstand your point due to my lack of knowledge, I'm sorry.
@@QuangNguyen-lf4lu There's a saying - there's no such thing as free lunch. Clean Code rules universally increase abstraction in the code and that is always at the price of performance. On top of that it could be argue that upsides (code that is easier to support/modify) are not useful at all. Game logic is not that transferable between games (outside of sequels) and I can easily imagine scenario where transferring code would be worse option, rather than writing new, better implementation. If you're new to programming, don't worry about what I said yet. You need good foundations first and SOLID will give you that.
Instead of the "classic" observer pattern, I'm mostly leaning towards the Event Bus pattern. Yes it comes with a cost of passing the reference of a player that invoked it, but still, based on my years of experience with it, it proved to be really beneficial.
Thanks for the timely video! I've been in the (slow) process of implementing scriptable object events in my game template - mainly to obsessively decouple my game components. And as soon as I got the concept working, I realized that in order to keep things fully decoupled, i wouod have to have events all over the place and I would no longer be able to effectively debug. I had a good thing going with a few singleton manager classes, but I let the nay-sayers lead me down a path of event-overload. This video has inspired me to go back to using a healthy balance of singletons and events where appropriate.
I didn't realize I was using the FlyWeight Pattern. I've been using it to separate logic and data as close to the MVC architecture as I can. I find myself using observer pattern the most however, using C# built-in delegeates.
When i was working on web services I realised i need an initialise event. I needed it but just notify those subscribed, but also run anything that tries to subscribe later. If anyone wants to see that code, I can publish it. It worked like a charm. No need to implement it manually every time. Just like a usual event. And you can stop thinking in order of execution.
You are the main reason I got into Game Development and Structuring the code and designing. I would also love to know about the State pattern and Task ( i create a new task for something i want to do and it completes the task and tells me it's done ( i think this is how it works ) ) pattern ( I don't know what it's called )
@Jason Weimann: In the case we need an Action that returns a string (e.g. for states like sleeping, burning, etc.), which gehts added to the Listeners in Pattern 2 (pattern after 7:45). Would you just use an Action for the listeners dict, or would you make two classes "IntStatBar" and "StringStatBar" or similar? Really interested in how you would solve this.
I think my biggest problems with game development (and I guess many else) is not knowing proper programming and design patterns used for game development. Writing code that implements your idea is one thing, but making it modular, easy to extend and not end up with spagehtti code is the hard part.
I feel the same way. I feel like I've been messing with game dev way too long to not have something released, and the biggest project-killer for me has been obsessing over clean, modular, extensible code instead of just getting the product working. I think accepting some small doses of spaghetti is beneficial in the grand scheme of finishing your ideas. Along the way, you can learn what mistakes were made and even go back to refactoring them as you gain experience later on. That's just my 2 cents
Excellent video! Really useful to hear about when to and when not to use these patterns. Please do some follow up videos on some of the other patterns you listed (Factory, Mediator, Prototype, and Service Locator would be of particular interest)
I definitely use the Observer pattern the most. I am probably overusing it and I've been known to send an event from the observer for another event. After watching this video though, I am going to start watching for that.
Hey Jason love the video. Favorite pattern is the Observer pattern but you definitely have to be ware of the things you mentioned and not abuse it. I use the Simple Event System (SES) implementation from the Unity store to achieve this, it's a Scriptable Object implementation so very flexible. I also believe the State pattern is very important
I love Singletons for Managers and I have no clue why so many people have an issue with it. The internet is filled with people telling others to stay away from them but in my experience... when I have only one Manager of something and I have children objects that want to just access values of that Manager, then I use a singleton because it's so helpful and straight forward. I've never came across an issue using singletons and maybe that's why I don't understand the controversies behind using them. 🤷♂️
The part starting at 7:45 took me more than 20min to understand in depth 😆but its really beautiful. Refreshed a lot of concepts I havent used in a while (expression bodied definition, Actions/Delegates) or didnt know (.ForEach, typecasting to an enum)👌 Also really clean extendable code.
Question/Request (the TL;DR Summary): A video on the Mediator Pattern. (Also, if/how it differs from Pub-Sub?). Also the Blackboard Pattern (which seems to be used in Game Dev as meaning nothing but generic public string storage, which is a bit different from what I've read about its original purpose in AI programming.) Finally, as part of both, your thoughts on frame load balancing. ##################################### This is kinda my final architecture question before I jump into the constructing a new project. I'll explain what I'm thinking of doing, and am requesting feedback from anyone on whether this sounds like a good idea or not, and whether this something commonly done in games. (My thinking about it leads me to assume that it surely must be a common approach, but maybe I'm totally missing something... which is kinda the point of this post.) I'm a little perplexed that I haven't heard this mentioned as an approach to handle game coding, so I'm afraid maybe I am missing something important. Also, is this nothing more than a slight variant of the mediator pattern, or the blackboard pattern, or whatever else is a common approach in game dev? It commonly seems to me that I don't want an Observer/Events pattern, but rather to write the "event" to a more permanent storage (though most things not saved forever) which is then scanned to fire off handling somewhere else (maybe even just raising a true event)... but that scanning isn't done every frame on every item. I'm thinking of something like a priority queue, or giving each item a window for how many frames it ideally should, and then must, go before it's processed, or something similar. It would be a GameWorld-Event-Holder-And-Dispatcher class (or module/wrapper/whatever). Many "presentation" events are needed in the frame (a sound accompanying a footstep), but it seems to me that many can wait half-a-second, many seconds, minutes, or even until a save or loading screen until they need to be handled (examples: awareness and reaction times in the moment, some kinds of NPC AI decisions, quest milestones & story beats, NPC attitude shifts, the spread of information in the game world, big long-term game consequences like supply/demand changes to an economy, and on and on). The reasons this seems like a good idea to me are: 1.) Allows a cleaner implementation of short term delays (like reaction times) than main-thread spamming coroutines. 2.) More intelligible. 3.) More traceable as to what's exactly happening. Observer pattern callbacks & events are, without more coding, fire & forget... and any such "more coding" would be quite similar to what I'm describing, so why not do that with structured consistency? 4.) Permits a greater level of control on the order in which events occur. 5.) Make game saves (and possible recoveries) cleaner. 6.) Is an easy way to put the game to be put into a specific state. 7.) ! Provides a clear & clean way to set up testing, just using data. 8.) Obviously aids in decoupling the system. 9.) Direct calls, rather than call-backs, are an order of magnitude faster. Of course, if the eventual processing includes raising an event, then that's not a gain... but maybe that's not always the case, and at least you can choose to do it when the measurable burden on the game is lower. 10.) You can track, acquire metrics, and even simply have a one-location access point to all these events which are driving the game, instead of having events firing off at various places all over the codebase. (I'm not suggesting a God class, but rather a more like a GameWorld-Event-Holder-And-Dispatcher class that then distributes the handling work elsewhere - perhaps merely by raising events itself - but it deals out that elsewhere-work at its own pace according to its own configured rules.) 11.) It seems to me that such a structure has at least the same, if not superior, clarity to firing off events. 12.) It seems to me it has at least the same, if not superior, development benefits as the common observer/events systems. You can segment the development, read off what has or hasn't yet been implemented, add something new to develop immediately or in the future, all with clarity by looking at the game world events that this class purports to know about. It looks to me to be SOLID-O (Open Closed Principle), and so should be very accommodating to iterative agile sprints and TDD. 13.) Perhaps a minor point, perhaps a big deal, but it would permit a fine grained reconstruction of the history of the gameplay. Before discarding the handled events, you could make summary of the day, or the descent into the dungeon, or whatever, picking out the notable events for that time span as desired. (You'd have a record that Bartholomew the Brave Barbarian died in the same fireball that killed Karl the Colossal Kaiju, and let the epic tales record as much... as well as recording that the assistance of Walter the Unwise Wizard is a mixed blessing. Or that you killed 40 god-damned cave bears on your trip walking from one town to the next in Skyrim.) 14.) Allows frame load balancing. If a gazillion events fire one frame because of some major occurrence, but virtually none fire in the next several frames, and if those gazillion events don't actually need to be handled in that one frame, then why would you want to do that? If a fireball kills the BBEG, then in that frame, using events, you're processing what must be processed immediately (the sound and visuals of the explosion, death animation, etc.), but also many things that could wait a second or two, so dozens of frames (UI consequences, XP gained, quest complete, relevant achievements), and many consequences that could wait a very long time before the player would encounter them (the change in the story line, others learning of the BBEG's death and whatever consequences follow from that, and so on). It seems nuts to me to pack all that handling into a single frame, especially since that's one moment where you definitely wouldn't want the game to hiccup. The only downside I can imagine is a violation of KISS, of adding undo complexity. But what I'm imagining doesn't strike me as too complex (heh... famous last words). It's a class whose data is a bunch of buckets, a routine for taking incoming bundled data representing game world events and choosing the correct bucket to drop that single bundled item into, and then a per-frame routine for grabbing the "next up" game world events, and a routine for looping through the "next up" that takes the data for each and sends it off to whomever is going to handle it. Also, this is perhaps contrary to the spirit of OO, and is by design a hub and potential bottleneck of sorts. But if it makes sense, it makes sense - I don't hold to an ideology that every corner of the codebase must be OO. And as I've said, it seems to me to be the good kind of hub... fast, simple, clarifying, and allowing superior code control. I can't see how it would be a performance bottleneck (again, famous last words). So... am I crazy? Is this the mediator pattern? Is this how game devs use blackboards in practice? Is this a good idea? Is this an obviously bad idea? Do devs do this... and if so, does it create problems that I haven't considered? Any feedback would be appreciated, especially because this is an upfront decision that I'm about to wed myself to.
This is a good list, I used all three in my first commercial solo game. When it clicked with me, what all three were kind of for, I started being able to mostly make all the game ideas I had. Still lots of work to make games, but much easier once I grasped c# well, knew some key patterns to solve my most common issues, and had a good grasp on the game engine.
What do you think about the ordered observer? It might be good for deciding who gets information first. You can set a priority. This seems more useful especially when using a singleton or static events. While script execution order affects the overall script, this approach only allows us to set priority for this specific event. public void RegisterObserver(IObserver observer, int Priority){ //Code }"
I'm surprised the strategy pattern isn't on here. I feel like once you're passed Unity "beginner" it's one of the most useful patterns in any software project.
Hi Jason, I found your video really good. Easy and fast examples to understand the patterns in a game development format. In this video you talked about references injection, as an alternative to Singleton pattern. I found videos about it but they where complex and hard to understand in a first view. Maybe you could help. But in general, I am very interested in this kind of videos about patterns in game development. So thanks! And greetings!
JetBrains Rider and that option is enabled by default. It's actually confused viewers of my channel because they thought they needed to type that in :)
Event means it can only be called from the scope of the class. Use Actions without the Event keyword if that suits your project better, but it does mean it can be called from anywhere. I had a project with a successful structure where I had a static POCO class called events and it had globally accessible events that I could subscribe to and invoke from anywhere.
I've taken an interest in the Observer pattern of late as something that bothered me about my last quite complex project was it had become quite a dependency hell with long call chains and for my next project I wanted to minimise dependencies as much as possible. I had a look a scriptable object events and Dapper Dino has a good video on doing this generically but try as I might I couldn't get on with it. There's just so much creation and wiring up that I gave up on it in the end. What I've gone with for now is UnityEvents or lists of which I can wire up in the inspector. If feels like a lot less hassle for the same result but I'll have to see how it works out going forward.
A good understanding of unity singleplayer development would be helpful. The networking side adds complexity, so it's important that you can read and understand the code to not get lost. Don't need to be an expert, but I'd recommend at least a bit of experience before trying multiplayer stuff. (It's really easy compared to 10-20 yrs ago though)
How were you loading the inventory? Typically what I'd do in a scenario like that is serialize/save the ID of the item, either a Unique integer ID, a string name, or a guid (name is the usual default for me). Then I grab the SO from a prefabmanager style database based on the name to re-populate the item instance.
Good stuff Jason. I'm with you on the Singleton pattern; I think it's pretty useful. I suppose anything can get abused or implemented all jacked up but I can't recall ever having a big problem with them. I'm pretty noob to game development but I'm a .NET developer by profession, for 15 years, and have encountered them in software at work and they've been fine, in those cases.
what is the name of pattern when i dont want to my code Call the other class i create to other class i created with different behaviour? Example, i Create PlayerInput and PlayerMovement in different component, But i dont want my Player input called my PlayerMovement on its method or variable. Then i use Unityevent So my Playermovement just Drag n Drop its Move(x,y) method to unityEvent OnMoveInput from Player Input
@@alialhabsyi5410 if you mean in a single script, then yes, sure, if you need. But in the whole project you can use as many patterns as you need for solving different problems
You choose the pattern that best allows you to accomplish the task you're trying to achieve. Part of being a good engineer is learning what patterns to apply to each situation. It definitely comes with experience. What typically happens is devs learn a "new" pattern and realize how powerful it is and then try to apply it everywhere. Over time you'll learn which patterns work best for different situations. You'll also learn when to recognize that the pattern you started with might not be the best choice and when to refactor.
Great video!! Master Jason, any thoughts on FMOD? Is it a must? Searched your channel but found no videos on it. Not sure if it's worth to learn it for a small solo game (turn based rpg). Thanks a ton!!
I'd like to see Abstract Factory. I tried and failed to do one I think bc of the MonoBehaviour. Also, Decorator and a good example of its use. Really any of the not in the top 10 usual patterns like Mediator, Prototype, Bridge, Visitor, Event Q, Proxy, Builder, Service Locator,
Hello, Jason! how you can use music or remixes of famous artists in your game without violating rights! Is it enough to indicate the artist and the title of the song?
2:30 is not a good pattern. In my game , every item is an entity . Quantity and durability are components . Inheritance can easily make big problems . I recommend using ECS pattern
There should be only one real singleton in a game and that is the service locator manager. Everything else should be a service. Using more than one singleton makes it almost impossible to do propert unit tests with your code, so, if you care about maintainability of your code - never use more than this singleton.
If your team is actually writing unit tests this is a valid reason to avoid singletons :) That only seem to be about 1/10 of them from what I've seen though :(
@@Unity3dCollege Unit tests are only one point, it is decoupling in general. And only because 9/10 teams produce bad code doesn‘t render the neccessarity invalid. More, I think, the use of singletons is one of the reasons, a lot of teams produce this bad code. If you can‘t test, reuse and scale it, why taking care of good code in the first place?
Aside from these, I think the State Pattern was the first proper pattern I learned for game development and it has been soooo helpful in many projects! Definitely recommend that one to people as well
Do you have a recommended resource to learn it. I've learned it but having lots of difficulties while using it so I'm thinking of taking a look at it again.
@@MafiaSniperThere are many resources, the gameprogrammingpatterns site has a good article for it (and other patterns), iHeartGamedev on YT had an easy digestible tutorial for it and I'm sure Jason has mentioned or showed it a couple of times too. I started with an enum to store what the current state is and then just made a switch statement in a single class and put all there, which worked but was a bit rigid and I had a huge file/class. Since then, a State is basically a separate class, which either implements an interface or inherits from an abstract state, and a StateMachine class keeps a dictionary where the key is the state type (can also be an enum, or System.Type directly) and value is of the state interface type (or the abstract state class type if you use that instead). You could also look through the code in existing state pattern assets, like on the asset store or on github for C#/Unity.
i think that "state pattern" is so usefull that it's not even considered as a pattern anymore is just like "the thing" but i agree one of the most powerfull you learn in early journey
@@MafiaSniper Bardent and "iheartgamedev" are good ressource, the longer version is called "finite state machine pattern" but since this comment is very old i think you might have already found a solution.
As an advanced beginner that has sort of hit a growth "wall" this video is a god send. So many things to look into and improve my skills with !
Glad it was helpful!
I use flyweight all the time, but I didn't know it was called that. I use Observer a lot, both for data binding, and for non UI related change events. I use Instance for managers, however, if I can get away with it, I prefer static classes.
I do the exact opposite naming for "On" events. I used to do it the way you are, but now I look at it from the point of view of the event calling Invoke. Invoke is the start, and the handler acts "On" the Invoke.
Thanks for these videos. Even though I've been programming a very long time, I'm always looking to learn something new.
Are you me?
I still think the clearest naming convention is for invoker to get the "On" and handler to get "handle" added to the name ex OnEventHappened += HandleEventHappened. ...
Could you add an example for the opposite naming for "On" events? Don't quite understand. Thanks!
@@aleksapetrovic7088 The event itself is the action, and the ones registered to that event are acting ON the action. So I might have an event called "ColorChanged", and any object acting on that event would register a method called "OnColorChanged".
Technically the ColorChanged event itself isn't changing any colors, it's just notifying objects that are registered to it that a color has changed, and it's passing it along. To me, that means it makes more sense to put the "On" on the method responsible for actually changing the color.
@@aleksapetrovic7088 I already replied, but I think it went into the RUclips black hole. Anyway, it's probably because I edited it a few times in a row. Here's my official cleaned up and well thought out edit of my original :)
I see the event itself as the action, and the methods registered to that action as acting ON that action. For example, if I had an event called ColorChanged, the object interested in changing color on that event, would register a method called OnColorChanged.
I have been messing around with Singleton for a while, and finally I understand why people argue about that pattern. Basically, Singleton does exactly the opposite of what other patterns try to do. While other pattern is a little bit complex to keep scripts private, not interacting with other scripts as much as possible to achieve "clean code", Singleton is not only simpler even when comparing with normal coding, it also makes script public and easier for every script to access that script, so it may lead to "dirty code".
In my opinion though, while obviously you should keep your code clean, why not make thing much more simpler when you dont need to. If a script fits 2 description that Singleton try to do (can only has 1 instance, and need to expose to everyone), what prevents us from using it? Of course we shouldn't abuse it, but as long as we understand why/when to use it, it shouldn't be a problem.
Clean Code (capital letters) is the main culprit of horrible application performance those days. It's a set of self-imposed "rules" that programmers come up with that only purpose is to make their job easier by sacrificing user experience.
@@SylvanFeanturi I'm sorry that I'm still new to programing, so I may not fully understand what you are trying to say. Yes, I agree that those rules' purpose is to make programmers' job easier, but I dont think any of them has anything to do with performance or user experience, at least from what I have learned. Clean code are just rules to keep code clean, arent they? They are not mean to increase or decrease performance. If the performance is horrible, shouldn't it be the responsibility of the programmers themself for not knowing how to optimize?
Once again, if I misunderstand your point due to my lack of knowledge, I'm sorry.
@@QuangNguyen-lf4lu There's a saying - there's no such thing as free lunch. Clean Code rules universally increase abstraction in the code and that is always at the price of performance. On top of that it could be argue that upsides (code that is easier to support/modify) are not useful at all. Game logic is not that transferable between games (outside of sequels) and I can easily imagine scenario where transferring code would be worse option, rather than writing new, better implementation.
If you're new to programming, don't worry about what I said yet. You need good foundations first and SOLID will give you that.
@@SylvanFeanturi @QuangNguyen-lf4lu I highly recommend Jason Storey's "Software Architecture in Unity" video on this topic.
@@midniteoilsoftware You could also watch ""Clean" Code, Horrible Performance" by Molly Rocket on this topic.
Instead of the "classic" observer pattern, I'm mostly leaning towards the Event Bus pattern. Yes it comes with a cost of passing the reference of a player that invoked it, but still, based on my years of experience with it, it proved to be really beneficial.
I do the same but call it the Mediator pattern.
@@midniteoilsoftware
I thought mediator pattern the actually name and that "bus" is just a naming cenvention
I prefer EventBoss 😎
Thanks for the timely video! I've been in the (slow) process of implementing scriptable object events in my game template - mainly to obsessively decouple my game components. And as soon as I got the concept working, I realized that in order to keep things fully decoupled, i wouod have to have events all over the place and I would no longer be able to effectively debug.
I had a good thing going with a few singleton manager classes, but I let the nay-sayers lead me down a path of event-overload.
This video has inspired me to go back to using a healthy balance of singletons and events where appropriate.
Singleton, state and observer patterns are my top three. Flywheel comes in 4th, but still critical for efficiency.
All three that you mention are the main ones I use. A good refresher for me. Thank you 😃
The ScriptableObject-instead-of-a-singleton pattern is really nice. Saved me a ton of work when I inevitably had to have isolated tests for debugging.
Exactly what I need! Thank you for catering to the intermediate noob
I didn't realize I was using the FlyWeight Pattern. I've been using it to separate logic and data as close to the MVC architecture as I can. I find myself using observer pattern the most however, using C# built-in delegeates.
When i was working on web services I realised i need an initialise event. I needed it but just notify those subscribed, but also run anything that tries to subscribe later. If anyone wants to see that code, I can publish it. It worked like a charm. No need to implement it manually every time. Just like a usual event. And you can stop thinking in order of execution.
You are the main reason I got into Game Development and Structuring the code and designing.
I would also love to know about the State pattern and Task ( i create a new task for something i want to do and it completes the task and tells me it's done ( i think this is how it works ) ) pattern ( I don't know what it's called )
If you've embraced Singleton, you probably also are using Factory.
@Jason Weimann: In the case we need an Action that returns a string (e.g. for states like sleeping, burning, etc.), which gehts added to the Listeners in Pattern 2 (pattern after 7:45). Would you just use an Action for the listeners dict, or would you make two classes "IntStatBar" and "StringStatBar" or similar?
Really interested in how you would solve this.
I think my biggest problems with game development (and I guess many else) is not knowing proper programming and design patterns used for game development. Writing code that implements your idea is one thing, but making it modular, easy to extend and not end up with spagehtti code is the hard part.
I feel the same way. I feel like I've been messing with game dev way too long to not have something released, and the biggest project-killer for me has been obsessing over clean, modular, extensible code instead of just getting the product working.
I think accepting some small doses of spaghetti is beneficial in the grand scheme of finishing your ideas. Along the way, you can learn what mistakes were made and even go back to refactoring them as you gain experience later on.
That's just my 2 cents
Excellent video! Really useful to hear about when to and when not to use these patterns. Please do some follow up videos on some of the other patterns you listed (Factory, Mediator, Prototype, and Service Locator would be of particular interest)
I’d love to see some deeper dives and examples into lesser known patterns
I definitely use the Observer pattern the most. I am probably overusing it and I've been known to send an event from the observer for another event. After watching this video though, I am going to start watching for that.
Your videos are a masterpiece :D
i really enjoy watching your videos ❤️
more about patterns please, we love patterns
Will do!
Hey Jason love the video. Favorite pattern is the Observer pattern but you definitely have to be ware of the things you mentioned and not abuse it. I use the Simple Event System (SES) implementation from the Unity store to achieve this, it's a Scriptable Object implementation so very flexible. I also believe the State pattern is very important
I love Singletons for Managers and I have no clue why so many people have an issue with it. The internet is filled with people telling others to stay away from them but in my experience... when I have only one Manager of something and I have children objects that want to just access values of that Manager, then I use a singleton because it's so helpful and straight forward.
I've never came across an issue using singletons and maybe that's why I don't understand the controversies behind using them. 🤷♂️
The part starting at 7:45 took me more than 20min to understand in depth 😆but its really beautiful. Refreshed a lot of concepts I havent used in a while (expression bodied definition, Actions/Delegates) or didnt know (.ForEach, typecasting to an enum)👌 Also really clean extendable code.
Question/Request (the TL;DR Summary): A video on the Mediator Pattern. (Also, if/how it differs from Pub-Sub?). Also the Blackboard Pattern (which seems to be used in Game Dev as meaning nothing but generic public string storage, which is a bit different from what I've read about its original purpose in AI programming.) Finally, as part of both, your thoughts on frame load balancing.
#####################################
This is kinda my final architecture question before I jump into the constructing a new project. I'll explain what I'm thinking of doing, and am requesting feedback from anyone on whether this sounds like a good idea or not, and whether this something commonly done in games. (My thinking about it leads me to assume that it surely must be a common approach, but maybe I'm totally missing something... which is kinda the point of this post.) I'm a little perplexed that I haven't heard this mentioned as an approach to handle game coding, so I'm afraid maybe I am missing something important. Also, is this nothing more than a slight variant of the mediator pattern, or the blackboard pattern, or whatever else is a common approach in game dev?
It commonly seems to me that I don't want an Observer/Events pattern, but rather to write the "event" to a more permanent storage (though most things not saved forever) which is then scanned to fire off handling somewhere else (maybe even just raising a true event)... but that scanning isn't done every frame on every item. I'm thinking of something like a priority queue, or giving each item a window for how many frames it ideally should, and then must, go before it's processed, or something similar. It would be a GameWorld-Event-Holder-And-Dispatcher class (or module/wrapper/whatever). Many "presentation" events are needed in the frame (a sound accompanying a footstep), but it seems to me that many can wait half-a-second, many seconds, minutes, or even until a save or loading screen until they need to be handled (examples: awareness and reaction times in the moment, some kinds of NPC AI decisions, quest milestones & story beats, NPC attitude shifts, the spread of information in the game world, big long-term game consequences like supply/demand changes to an economy, and on and on). The reasons this seems like a good idea to me are:
1.) Allows a cleaner implementation of short term delays (like reaction times) than main-thread spamming coroutines.
2.) More intelligible.
3.) More traceable as to what's exactly happening.
Observer pattern callbacks & events are, without more coding, fire & forget... and any such "more coding" would be quite similar to what I'm describing, so why not do that with structured consistency?
4.) Permits a greater level of control on the order in which events occur.
5.) Make game saves (and possible recoveries) cleaner.
6.) Is an easy way to put the game to be put into a specific state.
7.) ! Provides a clear & clean way to set up testing, just using data.
8.) Obviously aids in decoupling the system.
9.) Direct calls, rather than call-backs, are an order of magnitude faster.
Of course, if the eventual processing includes raising an event, then that's not a gain... but maybe that's not always the case, and at least you can choose to do it when the measurable burden on the game is lower.
10.) You can track, acquire metrics, and even simply have a one-location access point to all these events which are driving the game, instead of having events firing off at various places all over the codebase.
(I'm not suggesting a God class, but rather a more like a GameWorld-Event-Holder-And-Dispatcher class that then distributes the handling work elsewhere - perhaps merely by raising events itself - but it deals out that elsewhere-work at its own pace according to its own configured rules.)
11.) It seems to me that such a structure has at least the same, if not superior, clarity to firing off events.
12.) It seems to me it has at least the same, if not superior, development benefits as the common observer/events systems. You can segment the development, read off what has or hasn't yet been implemented, add something new to develop immediately or in the future, all with clarity by looking at the game world events that this class purports to know about. It looks to me to be SOLID-O (Open Closed Principle), and so should be very accommodating to iterative agile sprints and TDD.
13.) Perhaps a minor point, perhaps a big deal, but it would permit a fine grained reconstruction of the history of the gameplay. Before discarding the handled events, you could make summary of the day, or the descent into the dungeon, or whatever, picking out the notable events for that time span as desired.
(You'd have a record that Bartholomew the Brave Barbarian died in the same fireball that killed Karl the Colossal Kaiju, and let the epic tales record as much... as well as recording that the assistance of Walter the Unwise Wizard is a mixed blessing. Or that you killed 40 god-damned cave bears on your trip walking from one town to the next in Skyrim.)
14.) Allows frame load balancing.
If a gazillion events fire one frame because of some major occurrence, but virtually none fire in the next several frames, and if those gazillion events don't actually need to be handled in that one frame, then why would you want to do that?
If a fireball kills the BBEG, then in that frame, using events, you're processing what must be processed immediately (the sound and visuals of the explosion, death animation, etc.), but also many things that could wait a second or two, so dozens of frames (UI consequences, XP gained, quest complete, relevant achievements), and many consequences that could wait a very long time before the player would encounter them (the change in the story line, others learning of the BBEG's death and whatever consequences follow from that, and so on). It seems nuts to me to pack all that handling into a single frame, especially since that's one moment where you definitely wouldn't want the game to hiccup.
The only downside I can imagine is a violation of KISS, of adding undo complexity. But what I'm imagining doesn't strike me as too complex (heh... famous last words). It's a class whose data is a bunch of buckets, a routine for taking incoming bundled data representing game world events and choosing the correct bucket to drop that single bundled item into, and then a per-frame routine for grabbing the "next up" game world events, and a routine for looping through the "next up" that takes the data for each and sends it off to whomever is going to handle it.
Also, this is perhaps contrary to the spirit of OO, and is by design a hub and potential bottleneck of sorts. But if it makes sense, it makes sense - I don't hold to an ideology that every corner of the codebase must be OO. And as I've said, it seems to me to be the good kind of hub... fast, simple, clarifying, and allowing superior code control. I can't see how it would be a performance bottleneck (again, famous last words).
So... am I crazy? Is this the mediator pattern? Is this how game devs use blackboards in practice? Is this a good idea? Is this an obviously bad idea? Do devs do this... and if so, does it create problems that I haven't considered? Any feedback would be appreciated, especially because this is an upfront decision that I'm about to wed myself to.
This is a good list, I used all three in my first commercial solo game. When it clicked with me, what all three were kind of for, I started being able to mostly make all the game ideas I had. Still lots of work to make games, but much easier once I grasped c# well, knew some key patterns to solve my most common issues, and had a good grasp on the game engine.
I always use in each project of mine are Singleton, Observer, Command, State (if NPC in the game), Pool programming patterns.
What do you think about the ordered observer? It might be good for deciding who gets information first. You can set a priority.
This seems more useful especially when using a singleton or static events. While script execution order affects the overall script, this approach only allows us to set priority for this specific event.
public void RegisterObserver(IObserver observer, int Priority){
//Code
}"
I use singleton and observer pattern almost in every project.
I'm surprised the strategy pattern isn't on here. I feel like once you're passed Unity "beginner" it's one of the most useful patterns in any software project.
@Jason Weimann: Why no null check in the Awake Method of the Singleton? Couldnt another PrefabManager overwrite this one that way?
Hi Jason, I found your video really good. Easy and fast examples to understand the patterns in a game development format.
In this video you talked about references injection, as an alternative to Singleton pattern. I found videos about it but they where complex and hard to understand in a first view. Maybe you could help.
But in general, I am very interested in this kind of videos about patterns in game development.
So thanks! And greetings!
what IDE is this and how to enable this preview that shows what is the variable value in the inspector?
JetBrains Rider and that option is enabled by default. It's actually confused viewers of my channel because they thought they needed to type that in :)
I don't use the "event" modifier on my events (I use System.Action's basically all the time). Should I be? What's the impact of that keyword?
Event means it can only be called from the scope of the class. Use Actions without the Event keyword if that suits your project better, but it does mean it can be called from anywhere. I had a project with a successful structure where I had a static POCO class called events and it had globally accessible events that I could subscribe to and invoke from anywhere.
MVC / MVP, Observer, factory, sometimes singleton
I've taken an interest in the Observer pattern of late as something that bothered me about my last quite complex project was it had become quite a dependency hell with long call chains and for my next project I wanted to minimise dependencies as much as possible. I had a look a scriptable object events and Dapper Dino has a good video on doing this generically but try as I might I couldn't get on with it. There's just so much creation and wiring up that I gave up on it in the end.
What I've gone with for now is UnityEvents or lists of which I can wire up in the inspector. If feels like a lot less hassle for the same result but I'll have to see how it works out going forward.
Great video!
hey there Jason, what are the knowledge requeriments for your multiplayer extraction course? I'm looking into buying it.
A good understanding of unity singleplayer development would be helpful. The networking side adds complexity, so it's important that you can read and understand the code to not get lost. Don't need to be an expert, but I'd recommend at least a bit of experience before trying multiplayer stuff. (It's really easy compared to 10-20 yrs ago though)
i started doing the scriptable object part, but hit a wall with serialization, when loading the inventory the reference to the object just became null
How were you loading the inventory?
Typically what I'd do in a scenario like that is serialize/save the ID of the item, either a Unique integer ID, a string name, or a guid (name is the usual default for me). Then I grab the SO from a prefabmanager style database based on the name to re-populate the item instance.
What version of unity? 2022 works for me
yeah i discovered i had to do that later, i just didnt realize at first why just making a json of the entire inventory didnt work@@Unity3dCollege
Singleton pattern is my favorite one
For the flyweight pattern, couldn't you just make the shared variables static for the same effect?
I've seen "public event Action" and "public event EventHandler", which one should we use and when? Is there a difference?
Not sure if it will be strange or not but i'm using Commands variations all the way. All business logic is in commands and/or async commands
Good stuff Jason.
I'm with you on the Singleton pattern; I think it's pretty useful. I suppose anything can get abused or implemented all jacked up but I can't recall ever having a big problem with them. I'm pretty noob to game development but I'm a .NET developer by profession, for 15 years, and have encountered them in software at work and they've been fine, in those cases.
i design my own patterns and they give or take from a overall condition board.
what is the name of pattern when i dont want to my code Call the other class i create to other class i created with different behaviour?
Example, i Create PlayerInput and PlayerMovement in different component, But i dont want my Player input called my PlayerMovement on its method or variable. Then i use Unityevent So my Playermovement just Drag n Drop its Move(x,y) method to unityEvent OnMoveInput from Player Input
Is programming pattern is something we should choose only one at the early development ? or we can mix it with other programming pattern ?
Ofc not, different patterns for different problems. Some could be used at all times
And it's not a magical solution that'll make your game better, it's just a way to organize code to make it easier to work with
I see, so for example its possible to mix observer with singleton pattern.
@@alialhabsyi5410 if you mean in a single script, then yes, sure, if you need. But in the whole project you can use as many patterns as you need for solving different problems
You choose the pattern that best allows you to accomplish the task you're trying to achieve. Part of being a good engineer is learning what patterns to apply to each situation. It definitely comes with experience. What typically happens is devs learn a "new" pattern and realize how powerful it is and then try to apply it everywhere. Over time you'll learn which patterns work best for different situations. You'll also learn when to recognize that the pattern you started with might not be the best choice and when to refactor.
Great video!! Master Jason, any thoughts on FMOD? Is it a must? Searched your channel but found no videos on it. Not sure if it's worth to learn it for a small solo game (turn based rpg).
Thanks a ton!!
I'd like to see Abstract Factory. I tried and failed to do one I think bc of the MonoBehaviour.
Also, Decorator and a good example of its use.
Really any of the not in the top 10 usual patterns like Mediator, Prototype, Bridge, Visitor, Event Q, Proxy, Builder, Service Locator,
Great for the explanation
Glad it was helpful!
Hello, Jason! how you can use music or remixes of famous artists in your game without violating rights! Is it enough to indicate the artist and the title of the song?
Could you do something on flyweight pattern in ECS? I'm afraid you might create a bottleneck in systems by referencing data. Is that correct?
2:30 is not a good pattern. In my game , every item is an entity . Quantity and durability are components . Inheritance can easily make big problems . I recommend using ECS pattern
There should be only one real singleton in a game and that is the service locator manager. Everything else should be a service. Using more than one singleton makes it almost impossible to do propert unit tests with your code, so, if you care about maintainability of your code - never use more than this singleton.
If your team is actually writing unit tests this is a valid reason to avoid singletons :) That only seem to be about 1/10 of them from what I've seen though :(
@@Unity3dCollege Unit tests are only one point, it is decoupling in general. And only because 9/10 teams produce bad code doesn‘t render the neccessarity invalid. More, I think, the use of singletons is one of the reasons, a lot of teams produce this bad code. If you can‘t test, reuse and scale it, why taking care of good code in the first place?
Anstract Singleton Factory Proxy Observer Pattern
what’s the difference between this video and the one you made 3 years ago
About 1000 days
@@Unity3dCollegecontent wise? I was wondering if the older one is still relevant
ty for the video
Sometimes you have a sudden loud noises in the videos(1:30 or 3:07 for example), please consider making them a bit quieter or softer
Will do
I'm against singletons as ScriptableObjects give you the same functionality without locking up your code
Singleton
Singletons only
👌