One Wheel Studio For those triped up by the constructor in the monobehavior. Yeah... that was a bit of a brain fart. As I said at the end I generally wouldn't use a monobehavirour for this pattern - the constructor a holdover from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function if a MB is choosen otherwise the constructor is a solid way to do it.
The scriptable objects work amazing when combined with the interface + generic list approach. The trick is to just use the scriptable objects as a blueprint to allow designers to drag and drop completely new weapons all from the editor with persistence and reusability, then use these blueprints to factory in the actual runtime object instances
This IS the best "pattern" to resolve the issue with the weapons. Always impower designers without making them waiting for developers for every weapon they need to add, and streamline asset/game production :)
When you talked about adding multiple damage types and suggested a list of IDamage instances, I believe you missed the beautiful part of the strategy pattern. Simply create a utility class implementing IDamage, holding a list of IDamage instances and do the loop in the utility class. Your weapon class does not need to change if you want to change it's behaviour or strategy. This follows the open closed principle. Super clear instructions and great examples!
Honestly you should have more subscribers. I started learning C#/Unity in October and people like Brackeys, Jason Weimann, and now you, have been great resources for me to learn concepts, be they simple intros from one, to more in-depth teaching from another. Hope I can see more pattern tutorials in the future.
Thanks for the kind words. Brackeys and Jason set a high standard. Maybe some day this channel will get there ;) I'm glad the videos are useful! There are a few more programming pattern videos (4-5 total) on the channel, you can find a playlist on the channel home page.
For those who like written tutorials too or instead of video here's my write up: onewheelstudio.com/blog/2020/8/16/strategy-pattern-composition-over-inheritance
This pattern solves problems I have run into on the regular when trying to implement interfaces in a "smart" way. Thanks for making such great videos!!
Quality explanation. Especially when discussing the problems it solves. I think the hardest part of grasping any design pattern is the ability to see a real world use (well practical use). Instant sub! I hope the rest of your videos are half as good as this one. All the best, James
P.s. I used inheritence, instead of composition when creating my own Weapon class for my game Dread Rune. I was smirking and nodding when you were listing the various issues encountered. I have a chain of inheritence and it does get messy.
Thank you for the video, i really appreciate how clear and to-the-point they are, while also being easy to digest and enjoyable to listen to. S tier material
I know the Strategy Pattern, but I wasn't aware that it is possible to add a constructor for a MonoBehaviour. Seems like it gets called when the Component is added - pretty cool!
Yeah, that was a mistake. A bit of a brain fart if you will. It's not best practice to use a constructor. As I said at the end I generally wouldn't use a monobehavirour in for this pattern - it was a hold over from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function.
I think there are some downsides, but on a smaller project it’s likely a total non issues. You can search constructor and monobehaviour to see some of the posts on the idea.
First time in this channel and I love it. +1 sub. Perfect explanation with injecting code in the constructor to decouple the project. Also I would add an enum class with differents damage type.
awesome video, I loved your philosophy on reusability and the final toughts about alternative solutions and why not to use scriptable objects for this pattern
I learned about this at my college like 10 weeks ago but it was on have and was trying to think of how to implement that in unity then I saw this so thanks
I had a big typo in this but yeah I learned about design patterns using Java I learned about strategy, builder, factory, decorator and more but it was using Java not unity and in the classes I took for unity it was all monobehavior so I wasn’t sure how I could structure it like classes in Java but this made it easier to see
You probably should not use the constructor with the Sword class since it's inheriting from Monobehavior. Another bit cleaner way to implement this pattern is to use for example a WeaponStats scriptable object class with has an array of effects (scriptable object) which the weapon triggers. That way you can get rid of deep inheritance and it is a very designer-friendly workflow.
Great to see a unity implementation, but this example is quite a bit more complicated than the tipical examples like on the refactoringuru website... 4:40 The classes on the right don't implement a interface directly, but point towards a class (FireDamage) which is the one implementing the interface, the interface they point towards is described in the class they inherit from. (The last part was just describing in case I come back to this video cause I think I might want to use this at some point :V)
I feel like the item itself should be a scriptable object so that the game designer can very quickly and easily create and modify them in the editor. This scriptable object would just hold the data required for that weapon. Then the player could have a monobeavior that takes the data from the scriptable object in the constructor / switch weapon method that would wire up the weapon as seen in this strategy pattern.
Question about something here. If you had a scriptable object for your weapons, and in the scriptable objects set up a list of auxiliary damage types that the weapon had, such as empty for just a regular sword or fire and poison for a special sword, couldn’t you just have DoDamage always check the list and apply any kind of extra damage types to the damage? I don’t understand how setting the damageType for each individual weapon is more streamlined than this I think. I feel like you’re doing it with several classes when the way I’m currently doing it is with just a damage class and a weapon scriptable object. I’m not saying you’re wrong, I’m like a year into learning C# Unity. I’m just trying to figure out what you’re saying if you see this
There are always more ways to do things. I’ve done something similar to what you suggest with a stat and upgrade system. I think the size of the project and the nature of the project is important when deciding how to do things. If you just have a handful of damage types using a list on an SO totally makes sense. If you have 25 damage types it probably isn’t the best choice. Each approach has pros and cons. I don’t think you’ll find a system that’s always the best. It’ll only be the best for or more realistically “good enough” for the current project.
So, let me see if I'm understanding right...this pattern allows me to swap out behaviors at runtime. With the example of the weapon system, this means that we can have a weapon that can change its behavior. However, this means that we would need to have, technically speaking, just one weapon on scene. This weapon is the one that is going to change its behavior every time we need it, so for example, if I have a pistol and I want a shotgun, I press the swap key and the entire behavior of the gun is going to change, making it seem like I "changed" the weapon. It doesn't make sense to create different weapons (as objects on scene) because the premise of this pattern is to change the behavior of one object. If I were to create many weapons, none of them would require to change their behavior (because they've already have their own behavior). Now, because of the way this pattern works, if I wanted to upgrade my weapon (like, adding more ammo capacity), I would need to create a new behavior. This means that for every upgrade I would need to create new behaviors, so If have many upgrades and many weapons, I would end up with, well, a lot of classes (which you actually mentioned on the video). With this information, I can conclude that maybe, I could create many weapons, with their own behaviors, and only swap their behaviors for upgrades. This way, every weapon can have different levels of upgrades. Now, I don't know if this make sense (in terms of this pattern). Am I misunderstanding something? What about the last thing? Thanks in advanced.
I think you have the general gist of the pattern for sure. I would likely make a distinction between "behaviors" and "stats." One is logic the other is largely data or values. In many cases an "upgrade" may just be changing the stats. For example, I might make a "fire sword" class that defines how all fire swords behave (who they damage, who they can't damage, etc) and then on top of that you could have a stats class (damage, weight, cost, spell power, etc) who's values change when the sword is upgraded. This stats class could also potentially be shared by all weapons. Approaching it this way would greatly reduce the number of classes needed. (Also, I like the fire/ice thing as it has more clear differences in "behaviors" than a pistol vs. a shotgun). You could also define upgrade behavior within a class. So you could have your fire sword and your ice sword and each has logic for contolling how and when that particular sword will upgrade. Again this could greatly reduce the number of classes and probably make the system less error prone.
@@OneWheelStudio Oh f*ck, you're right. The stats interface...why I didn't thought about that? That works perfect for upgrading. Still, what about having multiple weapons? Thanks for the answer, btw
Yeah, that was a mistake. A bit of a brain fart if you will. As I said at the end I generally wouldn't use a monobehavirour for this pattern - it was a hold over from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function if a MB is choosen otherwise the constructor is a solid way to do it.
@@OneWheelStudio Oh, okay. Great explanation of pattern, but that mistake a little bit confused me and not only me, one guy in comments with nick "Globanus Opp", explain him please.
Это выглядит сложно, но я считаю, что это очень очень полезные знания. Буду пересматривать это видео и писать код с помощью паттерна "Стратегия", пока что я не пойму как это работает. Спасибо за видео!
Really awesome video! I helped me a lot with my project ^^ One thing I don't understand though, is, why would it be generally better to use interfaces and not an abstract class? If you made a class like FireDamage for example, you would almost surely only be inheriting from DoDamage (with another name in this case). And while making the base class inherit from scriptable object you'd have a much better time serialising it for prefabs in comparison to using interfaces, which are a pain to serialise (I have Odin, but still). Also, you'll a 100% sure have some common variables like a damage value for example, which to me it looks a lot cleaner to have in an abstract class than in a variable having to make a property for it. I might be losing the point, so if anyone could explain it, it would be really awesome!
I think it really just depends on the implementation. In my own work, I often start with an interface as that seems like the smallest footprint or cleanest method. It also leaves the base class open so to speak if I need to inherit from something else - and I really don't like complex inheritance trees. If I find that an interface is not a good fit, often when I need to implement a particular function the same way for every class or I need a variable (like you suggested) then I'll look at changing to an abstract class. No "right way" to do it. Just my two cents.
@@OneWheelStudio I see your point :) thanks for the clarification! All I was trying to say is that using this pattern to change an object's behavior at runtime is great, but having the ability to make prefabs of these objects with the behaviors already included is also something most people will want! So in this case using SOs paired with an abstract class seemed like a much more default choice to me, since making a serialised field for an interface in Unity is much more of a pain than making it for just a class (unless you use Odin or something like that), so that's why I was wondering why using interfaces over abstract classes by default. You probably weren't thinking of using the interfaces with prefabs though, so that might be the reason heheh! I really liked the video nevertheless, it helped quite a lot :D
Hi, I wonder how strategy pattern will be implemented in case I have more than 1 function doing the same thing in the base interface, but they take different input. Should I write like this? ------ void DoDamage(int _damage); void DoDamage(float _impactDmg, float _dmgOverTime, float _duration) ------ Given I don't want to split my interface into IDoDamageInstant and IDoDamageOverTime cause it will scale into too many interfaces later. In case of a weapon dealing dmg over time, it only needs the second function, so I think I should leave the implementation of the first function empty. Is that the best existing solution yet? Please let me know if u guys have any suggestions asap. Thank in advance
Hmm. That's an interesting question. You could do some sort of value check in the single parameter version and then call the multiple parameter version if it's needed? You might also include only the multiple parameter version and make use of default values for some of the parameters? Those are just a few ideas, it's hard to say what's best without understanding the whole project.
@@OneWheelStudio Thanks for your fast response. I really appreciate that tbh. Anw, I'll figure out a few things about my current project if u don't mind. I'm building a project in which player can upgrade power over time, such as throwing more shuriken at once, throwing fire bullets, icy bullets, etc. Moreover, enemies also can change across levels. They change attacking, death, moving behaviours. In short, it is quite similar to the Archero game.
@@OneWheelStudio At present, I'm using a "Weapon" class to control all attacking behaviours of an individual character. But I don't think it's a good structure to scale up.
@@jacktruong7151 You could also potentially create some sort of "weaponInfo" class that is passed into every weapon behavior and thus keeping to a single function on the interface. This weaponInfo clas could then contain all the information needed by the DoDamage class. This may just pass the buck so to speak, but it might be helpful. The weaponInfo class could even be a scriptable object?
Should the Weapon_Base Class have to to declare the IDoDamage namespace? Im trying to recreate this with a collision handler and im being told that the methods are out of context or not marked as static extern and namespace could not be found. Can anyone point me to were i might find help, or to a tutorial tht applies this practically in Unity?
Looks like this got resolved on the OWS discord? I was on the road, but ping me on discord if you're still having questions (I'm in one place all this week)
@@OneWheelStudio I will and thank you for this tutorial! I still learned a whole lot with this break down, I just need to iron out some detail but the way you display the code to convey flow of logic made me understand what the strategy was conveying! 🔥
I am trying to implement a strategy pattern for a weapon system in PUBG. Here, the base class Gun has attributes like a clip, type(AR, SMG, DMR, SR,etc ), damage, and an interface called IFireMode for single, auto, burst, and full-auto. So, what confuses me here if I implement the interfaces for Single, Burst, and Autofire modes and make different guns, won't that be a problem since our base class has only one IFireMode variable? For eg. M416 has auto, single, and burst fire mode as well. Also, making 3 interface variables feels unnecessary. Can you please suggest to me what can be done here or what type of interfaces can be there in a game like PUBG? Also, I would have to make a separate script for each weapon, right?
If understand what you're trying to do, which I might not... Each of your behaviors single, burst and auto would be swapped in or out based on player input. So when the player presses 1 (for example) you could set the IFireMode variable to single. Then when they press 2 you set the IFireMode variable to burst. And so on... You could simply create new instances of the behaviors each time the mode is switched OR maybe it makes sense to have a list of IFireMode and select items from that list to be the value of the IFireMode variable. Does that help?
@@OneWheelStudio Thank you so much. The thought of using an array/list also crossed my mind but I didn't give it much thought. And for my second question, I meant will I need to create a separate script for each weapon and attach it to its respective prefab? For ex. consider the Micro Uzi, an SMG with a higher fire rate. So like it will inherit the base class and set its attributes as to make it an SMG with high fire rate, put it in a script and then attach it to the prefab. Then make new scripts for every handgun tye, AR-type, etc. Am I right?
Yes, each weapon will need it's own script and it should be attached to the weapon prefab. Inside that class you can assign all the IFireMode instances as needed.
@@OneWheelStudio Thank you so much for your guidance. Your design pattern videos have helped me a lot. I am looking forward to more of them. Also, maybe if you like, you can talk about structuring game projects or how to devise an architecture for such projects. A lot of people like me know about concepts but fall short when it comes to real world applications. Thank you again. Keep up the good work👍❤️
I see why this is useful, but I am still struggling to learn how to use it. In the example given with different types of fire damage, why not just make a ScriptableObject with damageValue, weaponType and List ? If you make ANOTHER change that impacts all weapons (such as weaponRange), you will have to go to each class and write a value for it anyway, which is essentially the same as going to each scriptableObject and changing the value of the new variable made. I have tried to force myself to use this pattern for the past two weeks, and every attempt I made I just returned to ScriptableObjects after wasting hours and hours of work...
And on top of that, it is way more difficult to inject functions that require Update() or FixedUpdate(). If you have multiple types of knockback, and each knockback class has ApplyKnockback() that must apply the knockback in a different way every frame, why bother separating it with different classes when you can just shove all of that in the class that actually does the Update()? It feels like this pattern can only be flexible for simple data, but once you get into things that are a bit more complex, it immediately becomes obsolete. Someone please correct me, I want to learn.
i thing i understand your damage system but ther is one big problem Lech say you want have 2 weapon with fire damage for example and one off this weapon have 30 and 50 damage haw you by able to select that in your system ?
@@OneWheelStudio @One Wheel Studio yes i understand your idea but i don't liket at least for my project that is not good way that because is fps project the project im working on now i agreed is good idea Strategy Pattern for the project and to by onest i use Pattern for my self wean i try to create i projects most off the i crate i concept art or even i diagram before i make the system now i have go as fur to create diagram road map
It seems that after bolt 2 got cancelled, a new asset called ualive is created. Can u make a tutorial on that bolt extension cuz it claims that its even more powerful than bolt 2.
The constructor is sort of being duplicated that's true, but each one is somewhat unique (or could be). The behavior of fire damage (or ice damage or whatever) is not duplicated! It's contained in a single class. Meaning if I want to change the behavior of all the fire weapons I only have to do it one place. So I'd argue that the amount of code duplicated is significantly reduced (especially with a full implementation and not my simplistic pseudocode).
Re: “What if you have a weapon that does both fire and poison damage? Which class is it going to inherit from?” I wouldn’t use classes. I’d use delegates and implement interfaces. Would this work? It wouldn't be strategy, but this seems easier to me to read than the stragety pattern. public delegate void Burn(/* Do burn damage */); public delegate void Bludgeon(/* Smash */); interface Weapon { int DamageAmount { get; set; } } interface FireWeapon : Weapon { void DoBurnDamage(Burn burn); } interface BludgeonWeapon : Weapon { void DoSmashDamage(Bludgeon bludgeon); } public class FlamingHammer : FireWeapon, BludgeonWeapon { public FlamingHammer() { } public int DamageAmount { get; set; } public void DoBurnDamage(Burn burn) { throw new NotImplementedException(); } public void DoSmashDamage(Bludgeon bludgeon) { throw new NotImplementedException(); } }
My first attempt at something like what you suggest would probably be to make a list of behaviors. Each behavior being a different aspect of the weapon (fire, poison, etc) very much like if not exactly like in the video. I could then iterate through the list calling DoDamage (or whatever) on each item in the list whenever the weapon needed to do damage. This would let you compose individual weapons from several simpler behaviors to create more complex weapon behavior. I think this would be much simpler and extendable compared to creating individual classes that implement multiple interfaces. This may not strictly be the "strategy pattern" but it is still the idea of the pattern - that being using swappable components or classes to define the behavior of an object. In my current project I've done something similar with each behavior being a monobehavior in Unity. If you have more questions, feel free to reach out on the OWS discord there should be a link in the video description.
Great video :) I bet you could make some nifty game examples with Odin, I know you have familiarity with doing Odin content in the past. (Secret video request lol - especially since Unity killed Bolt).
I actually talked to the Odin guys about doing a video with this idea. We liked the idea, but couldn't quite figure out how to make it work and be an "Odin" video. But maybe... Maybe a dropdown that calls a function that switches the behavior. Hmm. Now you've got me thinking :)
You need to look into State Machine Pattern. If statements can be replaced by enums, but again we'll hit the road end. So, there comes the state machine pattern where we basically create a different class for each state of an AI and create Start and End methods to define variables when entering or leaving the state.
re: What if you wanted to mix weapon types. I know this isn't a strategy pattern (or is it?) but I'm wondering what you think: public delegate void Burn(/* Do burn damage */); public delegate void Bludgeon(/* Smash */); interface Weapon { int DamageAmount { get; set; } } interface FireWeapon : Weapon { void DoBurnDamage(Burn burn); } interface BludgeonWeapon : Weapon { void DoSmashDamage(Bludgeon bludgeon); } public class FlamingHammer : FireWeapon, BludgeonWeapon { public FlamingHammer() { } public int DamageAmount { get; set; } public void DoBurnDamage(Burn burn) { throw new NotImplementedException(); } public void DoSmashDamage(Bludgeon bludgeon) { throw new NotImplementedException(); } }
I was just asked the same question earlier today ;) So, I'll paste that answer. My first attempt at something like what you suggest would probably be to make a list of behaviors. Each behavior being a different aspect of the weapon (fire, poison, etc) very much like if not exactly like in the video. I could then iterate through the list calling DoDamage (or whatever) on each item in the list whenever the weapon needed to do damage. This would let you compose individual weapons from several simpler behaviors to create more complex weapon behavior. I think this would be much simpler and extendable compared to creating individual classes that implement multiple interfaces. This may not strictly be the "strategy pattern" but it is still the idea of the pattern - that being using swappable components or classes to define the behavior of an object. In my current project I've done something similar with each behavior being a monobehavior in Unity. If you have more questions, feel free to reach out on the OWS discord there should be a link in the video description.
One Wheel Studio
For those triped up by the constructor in the monobehavior. Yeah... that was a bit of a brain fart. As I said at the end I generally wouldn't use a monobehavirour for this pattern - the constructor a holdover from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function if a MB is choosen otherwise the constructor is a solid way to do it.
can you do a tutorial with a practical implementation? or maybe you have one and i missed it. Still have some issues wrapping my head around this.
The scriptable objects work amazing when combined with the interface + generic list approach. The trick is to just use the scriptable objects as a blueprint to allow designers to drag and drop completely new weapons all from the editor with persistence and reusability, then use these blueprints to factory in the actual runtime object instances
This IS the best "pattern" to resolve the issue with the weapons. Always impower designers without making them waiting for developers for every weapon they need to add, and streamline asset/game production :)
I'd love to hear more about that!
When you talked about adding multiple damage types and suggested a list of IDamage instances, I believe you missed the beautiful part of the strategy pattern. Simply create a utility class implementing IDamage, holding a list of IDamage instances and do the loop in the utility class.
Your weapon class does not need to change if you want to change it's behaviour or strategy. This follows the open closed principle.
Super clear instructions and great examples!
Honestly you should have more subscribers. I started learning C#/Unity in October and people like Brackeys, Jason Weimann, and now you, have been great resources for me to learn concepts, be they simple intros from one, to more in-depth teaching from another. Hope I can see more pattern tutorials in the future.
Thanks for the kind words. Brackeys and Jason set a high standard. Maybe some day this channel will get there ;)
I'm glad the videos are useful! There are a few more programming pattern videos (4-5 total) on the channel, you can find a playlist on the channel home page.
For those who like written tutorials too or instead of video here's my write up: onewheelstudio.com/blog/2020/8/16/strategy-pattern-composition-over-inheritance
The structure and presentation of these tutorials are among the best on RUclips. Fantastic tutorial.
This pattern solves problems I have run into on the regular when trying to implement interfaces in a "smart" way.
Thanks for making such great videos!!
Just discovered your channel - it's a hidden gem. You've just got a loyal subscriber.
Quality explanation. Especially when discussing the problems it solves. I think the hardest part of grasping any design pattern is the ability to see a real world use (well practical use). Instant sub! I hope the rest of your videos are half as good as this one. All the best, James
P.s. I used inheritence, instead of composition when creating my own Weapon class for my game Dread Rune. I was smirking and nodding when you were listing the various issues encountered. I have a chain of inheritence and it does get messy.
That it does! It's great when it's great and horrible when it's horrible.
woah, your content is very usefull for preople who are trying to get better at programming, keep up the good work
Thank you for the video, i really appreciate how clear and to-the-point they are, while also being easy to digest and enjoyable to listen to. S tier material
It's nice to put a face on all those wonderful Odin Inspector tutorial videos :D You have such a unique intonation!
Yep that’s me! Glad you like the Odin videos. Hopefully another batch of videos isn’t too far away. Hope this channel is useful too.
@@OneWheelStudio It's very helpful!
How the hell in whole world, this channel have very small number of followers. You are one of the best channels for coding.
I'd love to see more about that with in-game tutorial! Thanks for great guide!
This video deserves a lot more views
I know the Strategy Pattern, but I wasn't aware that it is possible to add a constructor for a MonoBehaviour. Seems like it gets called when the Component is added - pretty cool!
Yeah, that was a mistake. A bit of a brain fart if you will. It's not best practice to use a constructor. As I said at the end I generally wouldn't use a monobehavirour in for this pattern - it was a hold over from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function.
@@OneWheelStudio I see. But it actually works, so I don't really see a reason not to use it - unless there is some penalty that is not obvious.
I think there are some downsides, but on a smaller project it’s likely a total non issues. You can search constructor and monobehaviour to see some of the posts on the idea.
This was a great breakdown of the pattern - super useful!
This pattern would be amazing in combination with Scriptable objects 🤩
I actually implemented this to an extent with my Enemy Database and Managers 😂. This is great content man!
Glad it's useful!
First time in this channel and I love it. +1 sub.
Perfect explanation with injecting code in the constructor to decouple the project.
Also I would add an enum class with differents damage type.
Thanks. I hope it's useful somehow. Next pattern up will be the "Command Pattern" I think... :)
Great video! Super important especially for big games
awesome video, I loved your philosophy on reusability and the final toughts about alternative solutions and why not to use scriptable objects for this pattern
I learned about this at my college like 10 weeks ago but it was on have and was trying to think of how to implement that in unity then I saw this so thanks
I had a big typo in this but yeah I learned about design patterns using Java I learned about strategy, builder, factory, decorator and more but it was using Java not unity and in the classes I took for unity it was all monobehavior so I wasn’t sure how I could structure it like classes in Java but this made it easier to see
Good explanation and neat presentation. Cheers my man!
This reminds me of the first chapter of Heads Up Design Patterns
Very well explained ! Great work keep it up!
You probably should not use the constructor with the Sword class since it's inheriting from Monobehavior. Another bit cleaner way to implement this pattern is to use for example a WeaponStats scriptable object class with has an array of effects (scriptable object) which the weapon triggers. That way you can get rid of deep inheritance and it is a very designer-friendly workflow.
Great video! I always love your examples.
Now if I could get just half the views you get ;)
Congrats on your success!
@@OneWheelStudio You deserve much more. I've just plugged you in my discord. Keep up the good content!
Very beautiful, good job! 😍
Great way of teaching!
Quality material here =D
Great to see a unity implementation, but this example is quite a bit more complicated than the tipical examples like on the refactoringuru website...
4:40 The classes on the right don't implement a interface directly, but point towards a class (FireDamage) which is the one implementing the interface, the interface they point towards is described in the class they inherit from. (The last part was just describing in case I come back to this video cause I think I might want to use this at some point :V)
great work!! thanks for sharing
this js such nice video, hoping more pattern tutorials
I feel like the item itself should be a scriptable object so that the game designer can very quickly and easily create and modify them in the editor. This scriptable object would just hold the data required for that weapon. Then the player could have a monobeavior that takes the data from the scriptable object in the constructor / switch weapon method that would wire up the weapon as seen in this strategy pattern.
Loved it!
what is an example of doing fire bits?
It could be a specific animations, sfx, or maybe particle effects?
@@OneWheelStudio i have a player and 3 projectile gameobject and i would like to implement the strategy pattern. How would i go about it.
@@ygee5551 Is there a particular part that you are stuck on?
thanks. Could you show in next time how it's working ?
Question about something here. If you had a scriptable object for your weapons, and in the scriptable objects set up a list of auxiliary damage types that the weapon had, such as empty for just a regular sword or fire and poison for a special sword, couldn’t you just have DoDamage always check the list and apply any kind of extra damage types to the damage? I don’t understand how setting the damageType for each individual weapon is more streamlined than this I think. I feel like you’re doing it with several classes when the way I’m currently doing it is with just a damage class and a weapon scriptable object.
I’m not saying you’re wrong, I’m like a year into learning C# Unity. I’m just trying to figure out what you’re saying if you see this
There are always more ways to do things. I’ve done something similar to what you suggest with a stat and upgrade system.
I think the size of the project and the nature of the project is important when deciding how to do things. If you just have a handful of damage types using a list on an SO totally makes sense. If you have 25 damage types it probably isn’t the best choice. Each approach has pros and cons. I don’t think you’ll find a system that’s always the best. It’ll only be the best for or more realistically “good enough” for the current project.
Great tutorial, would like to see command pattern in game, and usage of command pattern with scriptable objects. Thanks
That’s definitely on my short list of videos. What did you have in mind with SOs and the command pattern?
So, let me see if I'm understanding right...this pattern allows me to swap out behaviors at runtime. With the example of the weapon system, this means that we can have a weapon that can change its behavior. However, this means that we would need to have, technically speaking, just one weapon on scene. This weapon is the one that is going to change its behavior every time we need it, so for example, if I have a pistol and I want a shotgun, I press the swap key and the entire behavior of the gun is going to change, making it seem like I "changed" the weapon.
It doesn't make sense to create different weapons (as objects on scene) because the premise of this pattern is to change the behavior of one object. If I were to create many weapons, none of them would require to change their behavior (because they've already have their own behavior).
Now, because of the way this pattern works, if I wanted to upgrade my weapon (like, adding more ammo capacity), I would need to create a new behavior. This means that for every upgrade I would need to create new behaviors, so If have many upgrades and many weapons, I would end up with, well, a lot of classes (which you actually mentioned on the video).
With this information, I can conclude that maybe, I could create many weapons, with their own behaviors, and only swap their behaviors for upgrades. This way, every weapon can have different levels of upgrades. Now, I don't know if this make sense (in terms of this pattern).
Am I misunderstanding something? What about the last thing?
Thanks in advanced.
I think you have the general gist of the pattern for sure.
I would likely make a distinction between "behaviors" and "stats." One is logic the other is largely data or values. In many cases an "upgrade" may just be changing the stats. For example, I might make a "fire sword" class that defines how all fire swords behave (who they damage, who they can't damage, etc) and then on top of that you could have a stats class (damage, weight, cost, spell power, etc) who's values change when the sword is upgraded. This stats class could also potentially be shared by all weapons. Approaching it this way would greatly reduce the number of classes needed. (Also, I like the fire/ice thing as it has more clear differences in "behaviors" than a pistol vs. a shotgun).
You could also define upgrade behavior within a class. So you could have your fire sword and your ice sword and each has logic for contolling how and when that particular sword will upgrade. Again this could greatly reduce the number of classes and probably make the system less error prone.
@@OneWheelStudio Oh f*ck, you're right. The stats interface...why I didn't thought about that? That works perfect for upgrading. Still, what about having multiple weapons? Thanks for the answer, btw
The lesson was great but what the heck happened with the subtitles xD
Why are u using contructor in MonoBehaviour? Everybody tolds to avoid constructors in monobehaviour.
Yeah, that was a mistake. A bit of a brain fart if you will. As I said at the end I generally wouldn't use a monobehavirour for this pattern - it was a hold over from some early testing and didn't get revised out. The pattern is still a good one and the same initialization could simply (and should) be moved to an Awake or Start function if a MB is choosen otherwise the constructor is a solid way to do it.
@@OneWheelStudio Oh, okay. Great explanation of pattern, but that mistake a little bit confused me and not only me, one guy in comments with nick "Globanus Opp", explain him please.
Это выглядит сложно, но я считаю, что это очень очень полезные знания. Буду пересматривать это видео и писать код с помощью паттерна "Стратегия", пока что я не пойму как это работает. Спасибо за видео!
I'm glad it was useful!
i'be been doing this without knwoing it has a name ;P
I can't find a similar video, just not about weapoin, but about monsters, only there monsters wrapped in each other, maybe someone saw?
Why not a singleton?
Really awesome video! I helped me a lot with my project ^^
One thing I don't understand though, is, why would it be generally better to use interfaces and not an abstract class? If you made a class like FireDamage for example, you would almost surely only be inheriting from DoDamage (with another name in this case). And while making the base class inherit from scriptable object you'd have a much better time serialising it for prefabs in comparison to using interfaces, which are a pain to serialise (I have Odin, but still). Also, you'll a 100% sure have some common variables like a damage value for example, which to me it looks a lot cleaner to have in an abstract class than in a variable having to make a property for it.
I might be losing the point, so if anyone could explain it, it would be really awesome!
I think it really just depends on the implementation.
In my own work, I often start with an interface as that seems like the smallest footprint or cleanest method. It also leaves the base class open so to speak if I need to inherit from something else - and I really don't like complex inheritance trees.
If I find that an interface is not a good fit, often when I need to implement a particular function the same way for every class or I need a variable (like you suggested) then I'll look at changing to an abstract class.
No "right way" to do it. Just my two cents.
@@OneWheelStudio I see your point :) thanks for the clarification!
All I was trying to say is that using this pattern to change an object's behavior at runtime is great, but having the ability to make prefabs of these objects with the behaviors already included is also something most people will want! So in this case using SOs paired with an abstract class seemed like a much more default choice to me, since making a serialised field for an interface in Unity is much more of a pain than making it for just a class (unless you use Odin or something like that), so that's why I was wondering why using interfaces over abstract classes by default. You probably weren't thinking of using the interfaces with prefabs though, so that might be the reason heheh!
I really liked the video nevertheless, it helped quite a lot :D
Hi,
I wonder how strategy pattern will be implemented in case I have more than 1 function doing the same thing in the base interface, but they take different input. Should I write like this?
------
void DoDamage(int _damage);
void DoDamage(float _impactDmg, float _dmgOverTime, float _duration)
------
Given I don't want to split my interface into IDoDamageInstant and IDoDamageOverTime cause it will scale into too many interfaces later. In case of a weapon dealing dmg over time, it only needs the second function, so I think I should leave the implementation of the first function empty. Is that the best existing solution yet?
Please let me know if u guys have any suggestions asap. Thank in advance
Hmm. That's an interesting question. You could do some sort of value check in the single parameter version and then call the multiple parameter version if it's needed? You might also include only the multiple parameter version and make use of default values for some of the parameters?
Those are just a few ideas, it's hard to say what's best without understanding the whole project.
@@OneWheelStudio Thanks for your fast response. I really appreciate that tbh.
Anw, I'll figure out a few things about my current project if u don't mind.
I'm building a project in which player can upgrade power over time, such as throwing more shuriken at once, throwing fire bullets, icy bullets, etc. Moreover, enemies also can change across levels. They change attacking, death, moving behaviours.
In short, it is quite similar to the Archero game.
@@OneWheelStudio At present, I'm using a "Weapon" class to control all attacking behaviours of an individual character. But I don't think it's a good structure to scale up.
@@jacktruong7151 You could also potentially create some sort of "weaponInfo" class that is passed into every weapon behavior and thus keeping to a single function on the interface. This weaponInfo clas could then contain all the information needed by the DoDamage class. This may just pass the buck so to speak, but it might be helpful. The weaponInfo class could even be a scriptable object?
@@OneWheelStudio thanks, I thought of it days ago but forgot about using scriptable object. Gonna try
Can we pls get an upadated tutorial on photon pun with bolt visual scripting pls?
It's a cool topic, but not one that I'm likely to do any time soon. Its a HUGE amount of work and really complex.
👍thanks
Should the Weapon_Base Class have to to declare the IDoDamage namespace? Im trying to recreate this with a collision handler and im being told that the methods are out of context or not marked as static extern and namespace could not be found. Can anyone point me to were i might find help, or to a tutorial tht applies this practically in Unity?
Looks like this got resolved on the OWS discord? I was on the road, but ping me on discord if you're still having questions (I'm in one place all this week)
@@OneWheelStudio I will and thank you for this tutorial! I still learned a whole lot with this break down, I just need to iron out some detail but the way you display the code to convey flow of logic made me understand what the strategy was conveying! 🔥
I am trying to implement a strategy pattern for a weapon system in PUBG. Here, the base class Gun has attributes like a clip, type(AR, SMG, DMR, SR,etc ), damage, and an interface called IFireMode for single, auto, burst, and full-auto.
So, what confuses me here if I implement the interfaces for Single, Burst, and Autofire modes and make different guns, won't that be a problem since our base class has only one IFireMode variable? For eg. M416 has auto, single, and burst fire mode as well. Also, making 3 interface variables feels unnecessary. Can you please suggest to me what can be done here or what type of interfaces can be there in a game like PUBG?
Also, I would have to make a separate script for each weapon, right?
If understand what you're trying to do, which I might not... Each of your behaviors single, burst and auto would be swapped in or out based on player input. So when the player presses 1 (for example) you could set the IFireMode variable to single. Then when they press 2 you set the IFireMode variable to burst. And so on...
You could simply create new instances of the behaviors each time the mode is switched OR maybe it makes sense to have a list of IFireMode and select items from that list to be the value of the IFireMode variable.
Does that help?
@@OneWheelStudio Thank you so much. The thought of using an array/list also crossed my mind but I didn't give it much thought. And for my second question, I meant will I need to create a separate script for each weapon and attach it to its respective prefab? For ex. consider the Micro Uzi, an SMG with a higher fire rate. So like it will inherit the base class and set its attributes as to make it an SMG with high fire rate, put it in a script and then attach it to the prefab. Then make new scripts for every handgun tye, AR-type, etc. Am I right?
Yes, each weapon will need it's own script and it should be attached to the weapon prefab. Inside that class you can assign all the IFireMode instances as needed.
@@OneWheelStudio Thank you so much for your guidance. Your design pattern videos have helped me a lot. I am looking forward to more of them. Also, maybe if you like, you can talk about structuring game projects or how to devise an architecture for such projects. A lot of people like me know about concepts but fall short when it comes to real world applications. Thank you again. Keep up the good work👍❤️
I see why this is useful, but I am still struggling to learn how to use it. In the example given with different types of fire damage, why not just make a ScriptableObject with damageValue, weaponType and List ?
If you make ANOTHER change that impacts all weapons (such as weaponRange), you will have to go to each class and write a value for it anyway, which is essentially the same as going to each scriptableObject and changing the value of the new variable made.
I have tried to force myself to use this pattern for the past two weeks, and every attempt I made I just returned to ScriptableObjects after wasting hours and hours of work...
And on top of that, it is way more difficult to inject functions that require Update() or FixedUpdate(). If you have multiple types of knockback, and each knockback class has ApplyKnockback() that must apply the knockback in a different way every frame, why bother separating it with different classes when you can just shove all of that in the class that actually does the Update()?
It feels like this pattern can only be flexible for simple data, but once you get into things that are a bit more complex, it immediately becomes obsolete. Someone please correct me, I want to learn.
i thing i understand your damage system but ther is one big problem
Lech say you want have 2 weapon with fire damage for example and one off this weapon have 30 and 50 damage haw you by able to select that in your system ?
You can set up the constructor of the fire damage class to have an input parameter for the damage. That way when it's created, you set the damage.
@@OneWheelStudio @One Wheel Studio yes i understand your idea but i don't liket at least for my project that is not good way that because is fps project the project im working on now i agreed is good idea Strategy Pattern for the project and to by onest i use Pattern for my self wean i try to create i projects most off the i crate i concept art or even i diagram before i make the system now i have go as fur to create diagram road map
It seems that after bolt 2 got cancelled, a new asset called ualive is created. Can u make a tutorial on that bolt extension cuz it claims that its even more powerful than bolt 2.
It definitely on my short list. I want to talk to the developer and get a bit more info but it seems exciting.
aren't you still duplicating code in each damage type?
The constructor is sort of being duplicated that's true, but each one is somewhat unique (or could be). The behavior of fire damage (or ice damage or whatever) is not duplicated! It's contained in a single class. Meaning if I want to change the behavior of all the fire weapons I only have to do it one place. So I'd argue that the amount of code duplicated is significantly reduced (especially with a full implementation and not my simplistic pseudocode).
Re: “What if you have a weapon that does both fire and poison damage? Which class is it going to inherit from?”
I wouldn’t use classes. I’d use delegates and implement interfaces. Would this work? It wouldn't be strategy, but this seems easier to me to read than the stragety pattern.
public delegate void Burn(/* Do burn damage */);
public delegate void Bludgeon(/* Smash */);
interface Weapon
{
int DamageAmount { get; set; }
}
interface FireWeapon : Weapon
{
void DoBurnDamage(Burn burn);
}
interface BludgeonWeapon : Weapon
{
void DoSmashDamage(Bludgeon bludgeon);
}
public class FlamingHammer : FireWeapon, BludgeonWeapon
{
public FlamingHammer() { }
public int DamageAmount { get; set; }
public void DoBurnDamage(Burn burn)
{ throw new NotImplementedException(); }
public void DoSmashDamage(Bludgeon bludgeon)
{ throw new NotImplementedException(); }
}
My first attempt at something like what you suggest would probably be to make a list of behaviors. Each behavior being a different aspect of the weapon (fire, poison, etc) very much like if not exactly like in the video. I could then iterate through the list calling DoDamage (or whatever) on each item in the list whenever the weapon needed to do damage. This would let you compose individual weapons from several simpler behaviors to create more complex weapon behavior. I think this would be much simpler and extendable compared to creating individual classes that implement multiple interfaces.
This may not strictly be the "strategy pattern" but it is still the idea of the pattern - that being using swappable components or classes to define the behavior of an object. In my current project I've done something similar with each behavior being a monobehavior in Unity.
If you have more questions, feel free to reach out on the OWS discord there should be a link in the video description.
Great video :) I bet you could make some nifty game examples with Odin, I know you have familiarity with doing Odin content in the past. (Secret video request lol - especially since Unity killed Bolt).
I actually talked to the Odin guys about doing a video with this idea. We liked the idea, but couldn't quite figure out how to make it work and be an "Odin" video. But maybe... Maybe a dropdown that calls a function that switches the behavior. Hmm. Now you've got me thinking :)
I'd like to see it applied to AI
That's where if statements are all over the place
You need to look into State Machine Pattern.
If statements can be replaced by enums, but again we'll hit the road end. So, there comes the state machine pattern where we basically create a different class for each state of an AI and create Start and End methods to define variables when entering or leaving the state.
re: What if you wanted to mix weapon types.
I know this isn't a strategy pattern (or is it?) but I'm wondering what you think:
public delegate void Burn(/* Do burn damage */);
public delegate void Bludgeon(/* Smash */);
interface Weapon
{
int DamageAmount { get; set; }
}
interface FireWeapon : Weapon
{
void DoBurnDamage(Burn burn);
}
interface BludgeonWeapon : Weapon
{
void DoSmashDamage(Bludgeon bludgeon);
}
public class FlamingHammer : FireWeapon, BludgeonWeapon
{
public FlamingHammer() { }
public int DamageAmount { get; set; }
public void DoBurnDamage(Burn burn)
{ throw new NotImplementedException(); }
public void DoSmashDamage(Bludgeon bludgeon)
{ throw new NotImplementedException(); }
}
I was just asked the same question earlier today ;)
So, I'll paste that answer.
My first attempt at something like what you suggest would probably be to make a list of behaviors. Each behavior being a different aspect of the weapon (fire, poison, etc) very much like if not exactly like in the video. I could then iterate through the list calling DoDamage (or whatever) on each item in the list whenever the weapon needed to do damage. This would let you compose individual weapons from several simpler behaviors to create more complex weapon behavior. I think this would be much simpler and extendable compared to creating individual classes that implement multiple interfaces.
This may not strictly be the "strategy pattern" but it is still the idea of the pattern - that being using swappable components or classes to define the behavior of an object. In my current project I've done something similar with each behavior being a monobehavior in Unity.
If you have more questions, feel free to reach out on the OWS discord there should be a link in the video description.
@@OneWheelStudio Thanks. And sorry for the double post. I thought I forgot to hit "reply" and hadn't posted it.