Happy Sunday! Would you be interested in having a system in your project reviewed and refactored on the channel? Make sure to join the Discord - in the future we may refactor more advanced examples than this simple system! Also, I've added new extension methods Vector2 and Vector3 RandomPointInAnnulus to the Utility library that ensure uniform distribution - see description for explanation!
I'm betting I'm not the only one who thought about the first half, "Oh yeah, that's easy, makes sense, that's what I would have done" and the second half "Wait, pause, what's that now??" :D Great stuff.
Ever since I started watching your videos my programming skills have literally skyrocketed. Your videos are a godsend. Unfortunately TH-cam is full of tutorials teaching you very very wrong concepts which a beginner will gladly consume. I did at least. Realizing how misleading they were took a lot of time. I guess that's part of the learning process... One thing I noticed: When referencing the prefab in the EnemyConfig class you could actually reference the prefab as type Enemy. That way there's no need to get the component when initializing. It's less prone to human error when dragging the prefab in the inspector too.
Your videos are a step above the standard Unity tutorials. This series is great! What better way to show how to apply what you've already been talking about than showing it in the bad code we're already writing :D Thanks!
I AM SO HAPPY I STUMBLED UPON YOUR CHANNEL! I recently made a game during a game project for my school that took 3 weeks, and i was pretty happy about with how it went. When I then came back to the project, I realized that everything was a complete mess. Every component was soo tightly coupled to eachother that every change i made meant i needed to change 10 other scripts. We slightly touched on design patterns in school but not enough to really make a difference in how i code. I did some research on different patterns and after stumbling upon your channel and watching almost all of your videos i realized i would need to break my baby (the game) and put it back together for the better. For the longest time i've been looking for a channel that teaches good coding practices and standards but all i've ever found are videos that are either too beginner friendly or don't touch on certain topics because they're "too complicated". YOU ARE DOING GODS WORK HERE! THANK YOU FOR THESE AMAZING VIDEOS!
I'm very happy to hear that. Actually the video I'm working on right now for Sunday is very similar to this one, it's all about refactoring, so stay tuned!
Wow! This is amazing. Exactly what I've been hoping you'd make - beginner's guide to practical applications of patterns. I look forward to more of these.
Hey Adam, Thanks to your videos, I'm getting a better handle on all these programming patterns every day. I really appreciate you teaching us how to be better programmers. Cheers,
This is EXACTLY the type of coding I like to watch. Refactoring is an art form. Knowing how or when to use a tool is arguably more important than knowing the tool itself. Very impressed. I can't wait for the next one of these!
Thank you so much for your content. I've been doing this a long time--I'm usually the old guy on the team shaking his fist at the clouds and saying, "why don't they teach GoF patterns to these kids?"--it's rare to find content that actually pushes me and exposes me to new things.
I loved this format, and it really show us a more hands on approach on how to refactor using patterns. If you want do more videos of this style please :D
Thank you for your videos. There is a dearth of intermediate to advanced tutorials for Unity on TH-cam. Many of the examples you have made I have adapted into my own projects and it has made me a much better coder.
Love this one! Thank you so much! You asked for video ideas so, if you haven't already done this, I would like to see a video or even a series on creating a template project. More specifically, code that you would want pre-existing for any new project so that you could quickly either copy the project or import the package(s), and start building/prototyping.
It's great to learn one more pattern and apply it to simple examples, it helps me understand them and know in what situations to apply it to them. Thank you very much, hopefully there will be a DI + pattern video soon!
This was great! One thing about the command pattern part of the video though. I feel like the jump from the old implementation with the strings and likely ifs to the whole command pattern implementation is too much. Someone who did the string implementation would be overwhelmed with the sudden new rather complex approach, especially given that they were in a level that uses magic strings. I'd love the refactors to cover some alternative ways to achieve things before jumping into the related pattern, talking about the problems current implementation has and the solutions new approach will provide. For example, before writing the command patterns implementation on this video, we could switch the magic strings to enums, talking about the problems this approach solves and does not solve, then go about implementing the pattern. Also must say I especially loved the factory pattern. I always had difficutly understanding the concept for some reason but this video made it so easy to understand. Also as a last nitpick, the new spawning logic with the strategy pattern looks like it can't actually achieve the old behaviour as it required the index of the loop to be used in the positioning logic, which the SetPosition method signature does not currently allow passing. How would one achieve this with the new implementation? Thank you :)
Thanks for the comment. In regard to the strategy, that's a good observation. I would probably suggest overloading the method in the strategy to accept optional params, perhaps a count or a ref to the List of enemies that have already been spawned.
Cool concept! I love flyweight SO approach "until we upgrade values" like you said in health example. That would also required me to refactor it. To be told, I would really love to see a modular upgrade system where we upgrade heroes & save it. Thanks for the huge effort on the video.
Thank you, vey useful. Hearing your thought process as you go along is almost unique at this level of Unity tutorial and so integral in understanding why a pattern is useful and how it can fit with other patterns. Hope you do more of these across differing use cases.
Hey, just wanted to say that this is some amazing content right there. Been watching your vids for some time and these are still some of the most useful, real-world usecases of programming patterns and more advanced coding techniques. No other creators bother to teach actual programming that is used in gamedev day-jobs, but stick to solo-dev, cutting-corners BS ^^ I certainly appreciated another take on that. Keep up the good work, hope your channel keeps on growing!
I followed along with the video. Took a while, but in the end it helped me understand the various patterns better. Also, it gave me a start on setting up an enemy spawner. Great stuff🤩😎
I'd love to learn more about audio systems c: Thanks for the video, never thought of using a strategy pattern with scriptable objects, it can be very useful
I'm chuffed that I at least managed to do a generator and factory for my spawners in a game jam recently. Though beyond that it got a little scrappy because of the pace! It was a sort-of RTS-cum-tower-defence, and where I got stuck was what you do with multiple things attacking a unit, and also balancing the game where things can attack from different distances
I've added a link to that Asset into the description, it's a handy tool you can buy for cheap. Also, Warped Imagination has a video on his channel about how to do that yourself.
Amazing! As per topics for future videos- how to handle card based games, both in terms of having many instances of cards with variations and global/local stats, and in terms of handling holders/placements etc. :)
I wouldn't necessarily make a new factory for every enemy type, but it really depends on the context of your larger game. What I might do instead is add an additional public method for the different type of enemy if it is significantly different than the first one. Another approach is to have factory return you a Builder instead of a completely configured enemy - that way the consumer class can configure the enemy as needed.
Thanks a lot! I really like this format a lot, yes it covers everything you have already covered on this channel, but it is a great refresher and gives us a lot of use cases. It isn’t only about understanding, but also about knowing when to use them. To be honest, If this was my project that you showed there, I would have used flyweight an that is it 🙂↔️. But yea thank you so much for that! I wish you a wonderful week. By the way, there is a big big discussion in my friend group. We are Dev Students studying Game Design, but we found our passion is in programming. So we want to work in the industry after finishing our bachelors. I really am in love with Unity, but I am kind of not too sure how the future will look like. Can you still recommend pushing in unity? :)
Thanks for the comment! In regard to your question, I personally think that Unity has a bright future - but to be honest, I wouldn't worry too much about the game engine itself. Once your skill level as a programmer reaches a certain level, it won't matter what engine you want to use - in a sense you will become language agnostic - the principles of software engineering and things like programming patterns apply to everything.
Great video! I'm curious where you've learned most of these patterns and how you developed a sense for when to use them or not. Were there any particular learning resources that helped you guide you?
The first code this dude wrote was more readable to me, I mean for solo devs it's an overkill, wasting of cpu cycles, abstraction nightmare and makes code harder to debug. I think it's like using a bazooka to kill an ant for small scale games, but good fit for big sized projects like MMOs. As backend devs we call this as abstraction hell. Big fat IAbstractionSpringBeanFactories are killing our sector that's why we are started to seeing more adaptation for golang like languages to reduce abstraction hell. Thanks ! Btw it'd be great if you could make a rewiev video on Casey Muratori's "Clean code horrible performance" video.
I understand your perspective; for solo developers or small-scale projects, abstraction can sometimes feel like overkill. I'll have a look at that video you mentioned.
What do you think about wrapping the Action instead of the command? That way the builder can still return the concrete class, not the interface BattleCommand.Build() { command.action = CommandActionDecorator.Wrap(command.action); // logging, etc return command; } for more flexibility, CommandActionDecorator has a Dictionary handlers that the user can register additional decoration for specific types. If none present - return the action
That might work in some scenarios, and might even be an improvement. But I also envision the BattleCommand becoming more complex, even having multiple Actions such as a pre and post action. I think it would really depend on the requirements of the user, but it's definitely something to consider.
How would you go about spawning the prefabs into specific locations in the game world using the strategy pattern you've setup? Would you create a list of transforms in a scriptable object? Or something else? Thanks
@@git-amend how would you expand this in order to have a list of transforms for each different enemy type in a clean way? Like a list for the ogres and for the goblins. Thanks again
@@git-amend hmm I tried playing around using the Placement Strategy Scriptable Object approach. But because it's a SO, I can't drag transforms in the game world into it
@@git-amend Would be interesting to see how you would combine it with the state machine. How to make it a bit less boilerplate so you can more quickly set and get variables. You’ve touched on also the scriptable object, I guess that’s key to reduce some of the setup in script. Thanks for your great content, by the way!
Well, I can't force anyone to adopt a specific implementation in their project, just offer suggestions on how I'd approach it. I certainly would not pass around actions as string values and have a series of conditional logic to handle those strings, and I also would not hard code that behaviour into the Enemy class. Of course there is always more than one way to solve a problem, and often will need to be considered in the larger context of the entire project.
Happy Sunday! Would you be interested in having a system in your project reviewed and refactored on the channel? Make sure to join the Discord - in the future we may refactor more advanced examples than this simple system!
Also, I've added new extension methods Vector2 and Vector3 RandomPointInAnnulus to the Utility library that ensure uniform distribution - see description for explanation!
I'm betting I'm not the only one who thought about the first half, "Oh yeah, that's easy, makes sense, that's what I would have done" and the second half "Wait, pause, what's that now??" :D Great stuff.
Great to see you watch these videos. It would be great if @git-amend would be a guest on the gamedev show. I don't know if Jason watches these videos.
Thanks for the comment! Glad you enjoyed the vid!
Ever since I started watching your videos my programming skills have literally skyrocketed. Your videos are a godsend. Unfortunately TH-cam is full of tutorials teaching you very very wrong concepts which a beginner will gladly consume. I did at least. Realizing how misleading they were took a lot of time. I guess that's part of the learning process...
One thing I noticed: When referencing the prefab in the EnemyConfig class you could actually reference the prefab as type Enemy. That way there's no need to get the component when initializing. It's less prone to human error when dragging the prefab in the inspector too.
Thanks for the comment! Great tip too, I totally missed that optimization while refactoring, good catch!
@@git-amenda part 2 video incoming?
Your videos are a step above the standard Unity tutorials. This series is great! What better way to show how to apply what you've already been talking about than showing it in the bad code we're already writing :D Thanks!
Glad you like them!
I agree. It's like an actual dev vs content creators. Just condensed, actual knowledge flowing straight into my brain.
I AM SO HAPPY I STUMBLED UPON YOUR CHANNEL! I recently made a game during a game project for my school that took 3 weeks, and i was pretty happy about with how it went. When I then came back to the project, I realized that everything was a complete mess. Every component was soo tightly coupled to eachother that every change i made meant i needed to change 10 other scripts. We slightly touched on design patterns in school but not enough to really make a difference in how i code. I did some research on different patterns and after stumbling upon your channel and watching almost all of your videos i realized i would need to break my baby (the game) and put it back together for the better.
For the longest time i've been looking for a channel that teaches good coding practices and standards but all i've ever found are videos that are either too beginner friendly or don't touch on certain topics because they're "too complicated". YOU ARE DOING GODS WORK HERE! THANK YOU FOR THESE AMAZING VIDEOS!
I'm very happy to hear that. Actually the video I'm working on right now for Sunday is very similar to this one, it's all about refactoring, so stay tuned!
Wow! This is amazing. Exactly what I've been hoping you'd make - beginner's guide to practical applications of patterns. I look forward to more of these.
Glad it was helpful!
Hey Adam,
Thanks to your videos, I'm getting a better handle on all these programming patterns every day. I really appreciate you teaching us how to be better programmers.
Cheers,
Great to hear! Thanks for the comment!
This is EXACTLY the type of coding I like to watch.
Refactoring is an art form. Knowing how or when to use a tool is arguably more important than knowing the tool itself.
Very impressed.
I can't wait for the next one of these!
Great, glad to hear that! Thanks for the comment!
This as a series is going to be awesome. Excited to see your process for reviewing and improving others code. Glad to see you're starting these.
Thanks! Maybe we can do one of these every couple months, I'll announce a bit before hand and take some submissions on Discord I think.
I like this more concrete explanation for patterns, its usually hard to see where to utilize them when its more abstract
Thanks! Will probably do a few more like this in the future
Thank you so much for your content. I've been doing this a long time--I'm usually the old guy on the team shaking his fist at the clouds and saying, "why don't they teach GoF patterns to these kids?"--it's rare to find content that actually pushes me and exposes me to new things.
Thanks for that! I know exactly what you mean! Glad to have you here.
This is a great format to show where it actually makes practical sense to implement the design patterns. I vote for more :)
Glad you like it!
I loved this format, and it really show us a more hands on approach on how to refactor using patterns.
If you want do more videos of this style please :D
Thanks will do!
Worth watching multiple times. The flyweight pattern used here helped me understand where it can be used.
Thanks! Maybe next time we'll tackle something a bit more complex as well.
Thank you for your videos. There is a dearth of intermediate to advanced tutorials for Unity on TH-cam. Many of the examples you have made I have adapted into my own projects and it has made me a much better coder.
You're very welcome!
Most valuable channel on youtube for me right now
Thank you so much!
10/10 you always knock these videos out of the park! good practices for audio sounds like a fun topic to explore!
Thank you!
You really help me push my Unity programming to the next level.
Great, glad to hear that!
Love this one! Thank you so much! You asked for video ideas so, if you haven't already done this, I would like to see a video or even a series on creating a template project. More specifically, code that you would want pre-existing for any new project so that you could quickly either copy the project or import the package(s), and start building/prototyping.
I’ve got a video on that topic coming soon!
It's great to learn one more pattern and apply it to simple examples, it helps me understand them and know in what situations to apply it to them. Thank you very much, hopefully there will be a DI + pattern video soon!
Glad it was helpful!
This was great! One thing about the command pattern part of the video though. I feel like the jump from the old implementation with the strings and likely ifs to the whole command pattern implementation is too much. Someone who did the string implementation would be overwhelmed with the sudden new rather complex approach, especially given that they were in a level that uses magic strings.
I'd love the refactors to cover some alternative ways to achieve things before jumping into the related pattern, talking about the problems current implementation has and the solutions new approach will provide. For example, before writing the command patterns implementation on this video, we could switch the magic strings to enums, talking about the problems this approach solves and does not solve, then go about implementing the pattern.
Also must say I especially loved the factory pattern. I always had difficutly understanding the concept for some reason but this video made it so easy to understand.
Also as a last nitpick, the new spawning logic with the strategy pattern looks like it can't actually achieve the old behaviour as it required the index of the loop to be used in the positioning logic, which the SetPosition method signature does not currently allow passing. How would one achieve this with the new implementation?
Thank you :)
Thanks for the comment. In regard to the strategy, that's a good observation. I would probably suggest overloading the method in the strategy to accept optional params, perhaps a count or a ref to the List of enemies that have already been spawned.
Cool concept! I love flyweight SO approach "until we upgrade values" like you said in health example. That would also required me to refactor it. To be told, I would really love to see a modular upgrade system where we upgrade heroes & save it.
Thanks for the huge effort on the video.
Thanks for the comment. That's an interesting idea for a video, I'll give it some thought!
First video that actually doesn't teach anything new to me, and I'm extremely happy about it! It means I've improved a lot since the first videos :)
Great to hear!
Thank you, vey useful. Hearing your thought process as you go along is almost unique at this level of Unity tutorial and so integral in understanding why a pattern is useful and how it can fit with other patterns. Hope you do more of these across differing use cases.
Glad it was helpful!
Absolutely fantastic video! 🤩 More just like this please!
Thank you! Will do!
Love the refactor vids! Great insight and examples of how to write clean and expandable code. Thanks as always!
My pleasure! Glad you liked it!
I like this content
Because looking at the mechanism of code modification helps beginners like me
Great, glad it's helpful! I'm glad this video resonates with people who are at different levels.
Hey, just wanted to say that this is some amazing content right there.
Been watching your vids for some time and these are still some of the most useful, real-world usecases of programming patterns and more advanced coding techniques. No other creators bother to teach actual programming that is used in gamedev day-jobs, but stick to solo-dev, cutting-corners BS ^^ I certainly appreciated another take on that.
Keep up the good work, hope your channel keeps on growing!
Thanks for the comment, I appreciate that! Lots more to come!
Love this! Definitely keep this series going i.m.o. As for a topic suggestion, what about an async/coroutine deep dive?
Great suggestion! I'll put that on the list!
This was a fantastic video. More refactoring videos with more advanced patterns. Great channel!
Thank you!
this is one of the best videos so far and they're pretty great all of them, so congrats!
Thanks for the kind words!
This is fantastic. This is really helpful for me. And as much as I like surprises, an Audio System would be interesting as well
Great to hear! Something interesting coming next week!
I followed along with the video. Took a while, but in the end it helped me understand the various patterns better. Also, it gave me a start on setting up an enemy spawner. Great stuff🤩😎
Awesome, glad to hear that!
Yay! Another refactoring video! Hope this video does well.
You know it!
I'd love to learn more about audio systems c:
Thanks for the video, never thought of using a strategy pattern with scriptable objects, it can be very useful
Glad it was helpful! Audio will be a topic soon for sure!
Yep, this new format is very useful.
Glad you think so!
I'm chuffed that I at least managed to do a generator and factory for my spawners in a game jam recently. Though beyond that it got a little scrappy because of the pace! It was a sort-of RTS-cum-tower-defence, and where I got stuck was what you do with multiple things attacking a unit, and also balancing the game where things can attack from different distances
Nice... I guess in a Game Jam scenario you do what you gotta do! Sounds fun though.
Amazing as always. Keep it up!
Thank you!
This is amazing! Great idea for a video.
Thanks! Glad you enjoyed it!
5:56 How do you put those icons in the hierarchy? Is it an asset?
In addition, great video, high quality content!
I've added a link to that Asset into the description, it's a handy tool you can buy for cheap. Also, Warped Imagination has a video on his channel about how to do that yourself.
ohhh! I love this content. so juicy. thank you!
You're welcome!
Amazing! As per topics for future videos- how to handle card based games, both in terms of having many instances of cards with variations and global/local stats, and in terms of handling holders/placements etc. :)
Not a bad idea, I'll write that one down!
@@git-amend legend!
How would you approach that if you have different enemy prefabs? Would you create new factories like RangedEnemy etc?
I wouldn't necessarily make a new factory for every enemy type, but it really depends on the context of your larger game. What I might do instead is add an additional public method for the different type of enemy if it is significantly different than the first one. Another approach is to have factory return you a Builder instead of a completely configured enemy - that way the consumer class can configure the enemy as needed.
Thanks a lot! I really like this format a lot, yes it covers everything you have already covered on this channel, but it is a great refresher and gives us a lot of use cases. It isn’t only about understanding, but also about knowing when to use them. To be honest, If this was my project that you showed there, I would have used flyweight an that is it 🙂↔️.
But yea thank you so much for that! I wish you a wonderful week.
By the way, there is a big big discussion in my friend group. We are Dev Students studying Game Design, but we found our passion is in programming. So we want to work in the industry after finishing our bachelors. I really am in love with Unity, but I am kind of not too sure how the future will look like. Can you still recommend pushing in unity? :)
Thanks for the comment! In regard to your question, I personally think that Unity has a bright future - but to be honest, I wouldn't worry too much about the game engine itself. Once your skill level as a programmer reaches a certain level, it won't matter what engine you want to use - in a sense you will become language agnostic - the principles of software engineering and things like programming patterns apply to everything.
@@git-amend I value your reply a lot. I owe you a coffee :)!
@@nixonscherbarth1974 Haha cheers!
Great video! I'm curious where you've learned most of these patterns and how you developed a sense for when to use them or not. Were there any particular learning resources that helped you guide you?
Mostly it comes from experience in software engineering. One good place I can recommend is refactoring.guru/
@@git-amend Thanks for the link! Appreciate it.
Another amazing video✅ I could guess some of the ways because of the all amazing videos before, keep up 👍
Awesome! Thank you!
You are awesome, dude!😎
Thanks! Glad you liked the vid!
The first code this dude wrote was more readable to me, I mean for solo devs it's an overkill, wasting of cpu cycles, abstraction nightmare and makes code harder to debug.
I think it's like using a bazooka to kill an ant for small scale games, but good fit for big sized projects like MMOs. As backend devs we call this as abstraction hell. Big fat IAbstractionSpringBeanFactories are killing our sector that's why we are started to seeing more adaptation for golang like languages to reduce abstraction hell. Thanks ! Btw it'd be great if you could make a rewiev video on Casey Muratori's "Clean code horrible performance" video.
I understand your perspective; for solo developers or small-scale projects, abstraction can sometimes feel like overkill. I'll have a look at that video you mentioned.
What do you think about wrapping the Action instead of the command? That way the builder can still return the concrete class, not the interface
BattleCommand.Build()
{
command.action = CommandActionDecorator.Wrap(command.action); // logging, etc
return command;
}
for more flexibility, CommandActionDecorator has a Dictionary handlers that the user can register additional decoration for specific types. If none present - return the action
That might work in some scenarios, and might even be an improvement. But I also envision the BattleCommand becoming more complex, even having multiple Actions such as a pre and post action. I think it would really depend on the requirements of the user, but it's definitely something to consider.
Great content as usual. I swear, I'm going to use these tips and definitely not leave my code as spaghetti.
Haha awesome, glad to hear that!
How would you go about spawning the prefabs into specific locations in the game world using the strategy pattern you've setup? Would you create a list of transforms in a scriptable object? Or something else? Thanks
Yeah, I'd probably make a strategy that exposed a list of transforms that could be configured in the editor.
@@git-amend how would you expand this in order to have a list of transforms for each different enemy type in a clean way? Like a list for the ogres and for the goblins. Thanks again
@@inkofthedragon It depends what you are doing I guess. You could just create a different spawner for each type if you need them separated.
@@git-amend hmm I tried playing around using the Placement Strategy Scriptable Object approach. But because it's a SO, I can't drag transforms in the game world into it
@@inkofthedragon You'll likely have to save the waypoints as a prefab to use this approach.
Amazing vids man love theam
Thank you! I appreciate that!
Nice.
Thank you! Cheers!
audio systems "sounds" great :D
Lol +1 points
Bro, I just found gold in form of your channel
Welcome aboard! Thanks for the comment!
Agree, it's way underrated! Love this channel! I'm a professional developer and it's a blessing to watch his content.
good video thank you
Glad you enjoyed it
Hi Adam, how about Blackbord pt2.
Maybe… what would you like to see in that?
@@git-amend Would be interesting to see how you would combine it with the state machine. How to make it a bit less boilerplate so you can more quickly set and get variables. You’ve touched on also the scriptable object, I guess that’s key to reduce some of the setup in script. Thanks for your great content, by the way!
also how to combine/interface with the Ipredicates and such, I think there are probably some neat tricks
@@Anerisian Hmm, yes that's a good idea.
The flyweight and strategy design patterns seem like a good fit. However, is the command pattern really needed?
Well, I can't force anyone to adopt a specific implementation in their project, just offer suggestions on how I'd approach it. I certainly would not pass around actions as string values and have a series of conditional logic to handle those strings, and I also would not hard code that behaviour into the Enemy class. Of course there is always more than one way to solve a problem, and often will need to be considered in the larger context of the entire project.
nice
Thank you!