EASY Stats and Modifiers in Unity | Broker Chain Pattern

แชร์
ฝัง
  • เผยแพร่เมื่อ 30 มิ.ย. 2024
  • Dive into Player Stats and Modifiers using the Broker Chain pattern! Uncover how this powerful design pattern can streamline your coding process and enhance game mechanics. Get ready to supercharge your programming skills and bring your game ideas to life like never before!
    Remember! In C#, Delegates are invoked in the order they are added to the event.
    Want to support me? 😀
    Buy me a coffee! ko-fi.com/adammyhre
    🔔 Subscribe for more Unity Tutorials / @git-amend
    Discord: / discord
    #unity3d #gamedev #indiedev
    ▬ Contents of this video ▬▬▬▬▬▬▬▬▬▬
    0:00 Stats
    2:53 Modifiers
    9:52 Pickups
    14:58 Equipment
    Source code: github.com/adammyhre/Unity-St...
    Countdown Timer: github.com/adammyhre/Unity-St...
    Assets Shown In This Video (Affiliate Links)
    Dungeon Mason Tiny Hero Duo: (FREE): assetstore.unity.com/packages...
    Tiny Heroes: assetstore.unity.com/packages...
    Hierarchy Icons: assetstore.unity.com/packages...
    Better Transform: assetstore.unity.com/packages...
    Better Mesh Filter: assetstore.unity.com/packages...
    Kyeoms VFX: assetstore.unity.com/publishe...
    Pure Nature 2 : Mountains: assetstore.unity.com/packages...
    HIGHLANDS - Stylized Environment: assetstore.unity.com/packages...
    Follow me!
    linktr.ee/gitamend
  • เกม

ความคิดเห็น • 123

  • @git-amend
    @git-amend  2 หลายเดือนก่อน +20

    Hi everyone! Hope this implementation of the Broker Chain pattern sparks your creativity! Smash that like button and join us on Discord! 👍

  • @nathan5694
    @nathan5694 2 หลายเดือนก่อน +14

    The biggest challenge I think a good stat modifier system faces probably could be an addendum video. Making your modifiers order of operation independent and also performant. You might have a modifier debuff that is designed to Clamp a stat, but if its applied first and then other modifiers are added you wont have consistent behavior. This is also extremely important with equipment modifiers where you might have things that multiplicatively buff Attack, so equipping add modifiers either before or after would have different results. Usually I solve this by creating a priority flag for any modifiers and then just iterating through that way, but I've never been super happy with that solution.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +7

      Yes, you bring up an excellent challenge. I will give this some thought, because it's definitely a problem many people face.

    • @UmbraGlobe
      @UmbraGlobe 2 หลายเดือนก่อน +1

      I personally solved this by creating more stat modifiers (add, increased, more, raw, override)

    • @crazyfox55
      @crazyfox55 2 หลายเดือนก่อน

      Addition, subtraction, multiply, divide, and clamps applied in that order still result in the largest stat bonus, so for your example, there is a simple solution of sorting, and the mediator can easily do that. Is there a modifier that breaks this? Stat ^ 2 can come after division. A non-increasing or wavy bonus would not fit with sorting but who should design a sign wave stat?

    • @nathan5694
      @nathan5694 2 หลายเดือนก่อน +1

      ​@@crazyfox55 Sorting is nlogn, so you do lose performance on that which may or may not be a problem depending on scope of the system, you can break it down to O(1) if you want to implement separate collections instead of one collection, but that loses extensibility, which could also be fine. There are solutions to this problem that will fit an individual games use case, but I like modularity in my systems and there is nothing I've been too happy with.

    • @drewvananne1796
      @drewvananne1796 2 หลายเดือนก่อน

      One optimization could be to only sort when a modifier is added and cache the value of the stat with the currently active modifiers. Instead of sorting and iterating across every modifier every time the stat property is accessed. This way if you only had a permanent attack buff from an equipped sword, it’d just have to calculate once upon equipping.
      But really I’d be surprised if this system was ever much of a performance bottleneck unless a game plans to have thousands of modifiers active at one time on a single character. Don’t worry too much about performance if these kinds of things aren’t updating every frame and aren’t allocating any memory. Sorting even several hundred modifiers by their enum value for operation type would be very fast.

  • @marc8150
    @marc8150 2 หลายเดือนก่อน +5

    Man it‘s always the same with your videos…
    I see a topic that I have some experience with, then after watching your video I feel like I have no idea what I was even doing before.
    Your code quality compared to other game dev channels is insane!
    Keep up the good work! :D

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Thanks! I hope you like the next video about Refactoring as well, which builds on this video!

  • @FireGmr3
    @FireGmr3 2 หลายเดือนก่อน +17

    Dude. Keep it up not only is this a great resource for learning game dev things but really good for seeing patterns in action

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +2

      More to come!

  • @prometheus1100
    @prometheus1100 2 หลายเดือนก่อน +12

    Amazing stuff. I FINALLY found a unity content creator aimed at developers that aren't complete beginners.
    Safe to say I subscribed immediately. Personally I'd love to see some roguelike specific content like random dungeon generation, loot systems, etc.. Thanks!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +5

      Welcome aboard! You'll probably like the Discord too!

  • @Thomas-yz3ny
    @Thomas-yz3ny 2 หลายเดือนก่อน +4

    That's the first time I see pure quality code in a game dev related video. Thank you! I'm quite advanced and it's a breeze and refreshing to follow you through!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Great to hear!

  • @DMIyce
    @DMIyce 2 หลายเดือนก่อน +1

    Man i love your stuff and presentation. I was looking for more advanced topics. I may not understand everything right away but these help me push myself and my knowledge further. Thank you so much!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Awesome, thank you!

  • @andreasmetz2438
    @andreasmetz2438 2 หลายเดือนก่อน +1

    Fantastic video as always. In a few weeks I'm at a point where I've got to implement a stat-system too and it will most certainly be inspired by this :)
    Keep up the amazing work!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Great, glad to hear that!

  • @umapessoa6051
    @umapessoa6051 2 หลายเดือนก่อน +1

    Hi, thanks for the video, i have a almost identical system in my Steam game and i didnt knew this had a name 😂
    One thing about the Timer, i also have a custom one implemented, you can have a static event when they start and a monobehaviour manager class that listen and is responsible for ticking and disposing of them, this makes easier to use them on non-monobehaviour class like FSMs 😊

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Nice! You might find this interesting, something that came out of a conversation on Discord the other day: gist.github.com/adammyhre/68a4c14f4478a9f64adc0759f7e4f402

  • @ragerungames
    @ragerungames 2 หลายเดือนก่อน

    Amazing content as always! One of the best youtube channel!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Glad you think so! Thanks!

  • @LuizMoratelli
    @LuizMoratelli 2 หลายเดือนก่อน

    Your videos are amazing! Really important stuff to learn and not just a bunch of simple tutorials.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Glad you think so! Thanks!

  • @migueldc6845
    @migueldc6845 2 หลายเดือนก่อน

    Git! I love your videos. Also the quizzes

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Glad to hear it!

  • @shukarullahshah
    @shukarullahshah 2 หลายเดือนก่อน

    Thank you so much, i was working on this task

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      You're welcome 😊

  • @BornToTroll-it5ju
    @BornToTroll-it5ju 2 หลายเดือนก่อน

    This channel is always jam-full with exclusive content that is a breath of fresh air for most advanced devs and I'm aware of that, but I do wish there a bit more access for us struggling intermediates. I mean, i thought I wasn't the world's worst coder; I know my Reflection from my interfaces, what linked lists, know a few patterns such as Observer, Command, Service Locator etc. , but apparently, I was wrong - as evidenced by the fact ninety-percent of the methodology shown here goes over my head (lol)
    It would be dream come true if some kind soul would release breakdowns of each vid. Example: "Ok, why does he use Query that invokes instead a simple for...loop? Lets take a look at some examples of how loops you've been using for years fail solid principles and how they could land you in hot water with game dev"
    You know what I mean?
    A companion channel to this one, with slightly more intimate breakdowns of the paradigms would be brilliant. And obviously I'm not expecting git-amend (Adam?) to go through all that trouble himself, as he should keep aiming towards educating the highest tier students for whom it's most beneficial, and devote his time to that, obviously. So this is more of a plea for someone else out there, to step in and helps us coding whelps to to demystify what some of us find to be quite esoteric material, and come forth with something that has a bit of a 'For Dummies' edge to it. I can't speak for other scripters but I'd certainly have worlds of gratitude for something like that.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thank you for your honest feedback. I appreciate your engagement and understand that jumping from intermediate concepts to design patterns like the Broker Chain can be challenging. It’s important to me that my content is accessible and useful to developers trying to move to an advanced level.
      To clarify the use of a Query object instead of a simple loop: In complex systems, using something like a multicast delegate helps manage a sequence of operations or notifications in a controlled manner. This is similar to a for loop where each subscribed method is called in order. However, it provides more flexibility and adherence to software design principles, such as single responsibility and open/closed principle, by decoupling the operations from the executor. We may migrate to using a more straight forward loop in a future video as we add more features that will require further separation.
      I will take your suggestion to heart and explore ways to break down these advanced concepts and design choices a bit more in future videos. Your learning journey matters, and I want to support it. Remember, what feels complex now will soon become second nature to you!

    • @BornToTroll-it5ju
      @BornToTroll-it5ju 2 หลายเดือนก่อน

      ​@@git-amend Thanks for the reply. Just to reiterate, there's no pressure for you to adjust your style in any manner. It's on me to do the catching up. Thanks for devoting your time and efforts to this channel.

  • @bluzenkk
    @bluzenkk 2 หลายเดือนก่อน +1

    thankyou , i learn alot from this.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Glad to hear that!

  • @SuperTungbi
    @SuperTungbi 2 หลายเดือนก่อน

    Shit, I am enlightened every time your video release, thank you so much for the beautiful work ❤

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thank you!

  • @MrOfearos
    @MrOfearos หลายเดือนก่อน

    Many things I could say, bottom line is: you're a legend and I hope u know how much we appreciate you and your content

    • @git-amend
      @git-amend  หลายเดือนก่อน

      Thank you so much! Very encouraging to hear that!

    • @MrOfearos
      @MrOfearos หลายเดือนก่อน

      @@git-amend sure! You fill a gap that was sorely missed in the game dev toturials world and you do it in such a great quality

  • @PurpleDaemon_
    @PurpleDaemon_ 2 หลายเดือนก่อน +1

    Very cool implementation, thanks for sharing! I definitely can improve my buff system with some ideas from this video.
    Two small things im not sure about:
    1) I would avoid using a linked list for modifiers, since it's not cache-friendly for iterating by, and you still can remove from a normal list in O(1) by simply swapping the desired element with the last one before the actual deletion, since the order in which modifiers are applied should not affect the final result.
    2) I really dont like that we have to check the type in Visit method. Unfortunately, I myself don’t yet know how to avoid this, other than to create a more specific IVisitable interface that has stats.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thanks for the comment. You are correct, the actual list in the video doesn't matter in regards to order, since that isn't what's applying the modifiers. As for the Type, yeah I'm not sure what an elegant solution to that is yet either. It's on the diffuse brain now.

    • @Soraphis91
      @Soraphis91 2 หลายเดือนก่อน +2

      > 1) I would avoid using a linked list for modifiers, since it's not cache-friendly for iterating by, and you still can remove from a normal list in O(1) by simply swapping the desired element with the last one before the actual deletion, since the order in which modifiers are applied should not affect the final result.
      I also oppose the linked list, but if you have things like multiplicative modifiers order might inded play a role. I'd probably store a List and flag the objects as dead (as even the skipping over a few dead entries is probably way faster than dereferencing the linked list entries), and shrink it whenever the last element is flagged as dead (since that is an O(1))
      > 2) I really dont like that we have to check the type in Visit method. Unfortunately, I myself don’t yet know how to avoid this, other than to create a more specific IVisitable interface that has stats.
      the visitor pattern seems here a bit over-engineered. As the Powerup could also just `ApplyPickupEffect(GetComponent())` in the OnTriggerEnter. Number of GetComponent calls stays the same, type check in visit is gone, visit is gone alltogether and Accept method is also gone.
      alternatively making IVisitor generic (IVisitor where T : IVisitable) so you have to implement a concrete method for every IVisitable the Visitor can accept.
      this would be in-line with the idea of the visitor pattern: having few/a fixed amount of different IVisitables (since adding visitables would be a lot of code change) to receive the benefit of adding Visitors being not that much work.
      3) Retrieving stats is a query.
      changing the stats can only happen if a buff is added/removed so the resulting value can be pretty easily cached and the query only executed once per change in the mediators list.

  • @skyswimsky1994
    @skyswimsky1994 2 หลายเดือนก่อน

    Haven't heard of this pattern before even in passing. Reminds me somewhat of the Decorator pattern, though doing some research on the topic of "Broker Chain/Chain of Responsibility and Decorator" I'm not the only one. As a ignorant blanket statement I wouldn't say apples vs oranges as much as the Broker Chain being another level of abstraction for more potential control.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Absolutely! While the Broker Chain pattern is more common in enterprise applications, the context of video games is often used to teach the pattern because they provide a dynamic and relatable context for understanding how responsibilities can be distributed and managed across different objects.

    • @8BitsPerPlay
      @8BitsPerPlay 2 หลายเดือนก่อน

      @@git-amend Just checking is the Broker Chain pattern and the Chain of Responsibility pattern the same. It seem like one started with more generic and goes to more detailed logic classes. Just wondering if they are considered the same on a technical level.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      @@8BitsPerPlay They are a little bit different. While both patterns deal with distributing requests among a set of handlers, the Broker Chain uses a central broker to manage communication, which reduces coupling between handlers, unlike the more linear and direct chaining of handlers in the Chain of Responsibility.

    • @8BitsPerPlay
      @8BitsPerPlay 2 หลายเดือนก่อน

      @@git-amend Okay that makes a lot more sense. When trying to find more about the Broker Chain pattern I only kept finding information about Chain of Responsibilities.

  • @williamedwards3911
    @williamedwards3911 หลายเดือนก่อน

    @git-amend - thank you for a great video - just getting wise to your channel. Presumably I could swap out the enum (StatType) for a Type And SubType maybe as ScriptableObjects?

    • @git-amend
      @git-amend  หลายเดือนก่อน +1

      Seems like something that is not too hard to change, and might make it a bit more user friendly.

  • @SetZor666
    @SetZor666 2 หลายเดือนก่อน

    It's great, I woke up this morning pondering some ways to handle my game's player/enemy stat modifiers and this video pops up a day after i subbed to the channel. what i would love is an addressables tutorial that shows more than just loading the stage or static objects. can't seem to find one anywhere. what if i want to have a character model selection (multiplayer game) and all those models are addressable, what would be a good strategy/pattern to handle this.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thanks for the comment! An Addressables video about loading things on the fly might make for a good video. I'll put it on my list.

  • @bbrainstormer2036
    @bbrainstormer2036 2 หลายเดือนก่อน

    Now this is helpful!

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Right on!

  • @adek445
    @adek445 2 หลายเดือนก่อน

    Really great video. I've got kinda lost on Queries but will watch again, implement and figure this out.
    The thing I wonder is that here in this implementation of broker chain pattern we will have to add multiple components of StatModifier if we want to change couple of stats at the same time. I probably would see a little change to have stats modification maybe as a SO and have them as a list in stat modifier, or as some serializable type also in list.
    How would you approach such problem - items could change multiple stats? :)

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      I think you could add an overload to accept a list, seems straightforward

  • @kevin41307
    @kevin41307 2 หลายเดือนก่อน

    THANK A BILLION. That's what I am looking for.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Right on!

  • @rofu8096
    @rofu8096 2 หลายเดือนก่อน

    perfection

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Thanks!

  • @charboa531
    @charboa531 2 หลายเดือนก่อน +1

    Hi, I really like your tutorials and game design pattern videos in particular. It has been 3 years since I started game development and I was thinking I am at a level that I can develop and ship a game with my current knowledge of object oriented programming and Unity. I am probably junior-mid level considering you are a senior, and every time I watch one of your tutorials I try to implement that design pattern to my workflow and it kinda creates an endless cycle of learning and applying new things to my code. And this led me to think my eager to learn new design patterns and new programming concepts puts a barrier to my ability to finalize a product. What would you suggest to a fellow junior, should I learn and practice as much design patterns as I can to enhance my workflow or should I focus on finishing my games even though they are developed in less efficient way?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      The learning never ends! Keep working on your projects… if you stop creating and just learn, you’ll be learning forever. It’s best to always do both!

  • @aynotation5202
    @aynotation5202 2 หลายเดือนก่อน

    Good channel to learn thins

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thank you!

  • @damonfedorick
    @damonfedorick 2 หลายเดือนก่อน

    nice

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Thank you!

  • @user-rm2pj9jf8s
    @user-rm2pj9jf8s 2 หลายเดือนก่อน +1

    I think you're really good at coding.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Thanks!

    • @user-rm2pj9jf8s
      @user-rm2pj9jf8s 2 หลายเดือนก่อน

      ​@@git-amend If you don't mind, why don't you teach me an assembly definition definition next time? Your code is concise and beautiful, but I think modularization should also have an assembly definition.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      @@user-rm2pj9jf8s Sure, Assemble Definitions is on my TODO list!

    • @user-rm2pj9jf8s
      @user-rm2pj9jf8s 2 หลายเดือนก่อน

      @@git-amend It's a rude and annoying question, but thank you for answering

  • @silchasruin4487
    @silchasruin4487 2 หลายเดือนก่อน

    I'll have to experiment with this more if I need modifiers and stat changes during runtime for my game but I'm interested in testing it out by creating a simple implementation using Sphere colliders set as triggers which could potentially adjust enemy behaviours or damage/speed stats. On a seperate note, I'm trying to look into a type of Director type AI. Similar to the Director from Left 4 Dead. What I'm thinking about is reducing the overhead from multiple smarter individual enemies and have a director that can take the number of enemies, types of enemies and see what the player is doing or even what weapon the player is holding and come up with strategies such as flanking, taking cover, and more. I'm starting small by monitoring where the player is looking, where player is not, where the player cant see and so on and working from there.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Sounds like a very interesting idea, a little bit similar to what I want to do with the Mediator and GOAP videos but with a unique twist. Let me know how you get along with it!

    • @silchasruin4487
      @silchasruin4487 2 หลายเดือนก่อน

      @@git-amend I'll have to DM you on Twitter once I have something functional, I'm still working out the systems for cover and flanking now that I have the FOV stuff out the way. I'll do a test with the Mediator pattern to test if working with 200 enemies on screen is more performant than having each enemy use its own complex logic.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      @@silchasruin4487 Sounds good, I look forward to it.

  • @halivudestevez2
    @halivudestevez2 2 หลายเดือนก่อน +1

    the more tutorial I watch from you, the more I feel we get some overcomplicated stuff, which is easy to create bugs and errors.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +3

      While some content may appear complex, it often aims to demonstrate practices like type safety, encapsulation and separation of concerns, which actually lead to less bugs in the long run and facilitating scalability in more complex games.

    • @28082989
      @28082989 2 หลายเดือนก่อน

      Is either overcomplicating things or the Broker Chain Pattern is awful, and for me is the second one.
      He might be implementing the Broker Chain Pattern correctly, but just imagine adding more StatTypes to this system... no thank you!

  • @littlerookey5466
    @littlerookey5466 10 วันที่ผ่านมา

    Hi, what is the name of website you're using to plan before code? The one ur using to make diagrams. I really like it. Also your workflow of building system is so helpful! My goal as a programmer is you!

    • @git-amend
      @git-amend  10 วันที่ผ่านมา

      Thank you! That's Excalidraw for Obsidian (th-cam.com/video/o0exK-xFP3k/w-d-xo.html). You can use it standalone too at their website.

  • @rechnight
    @rechnight 2 หลายเดือนก่อน +1

    Hey Adam, do you have psychic powers? Just started writing up a CharacterStat class and wondering how to deal with modifiers and your video was uploaded! 😂

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Nice! I do not have psychic powers, I don't think, but this was a much requested video!

  • @crazyfox55
    @crazyfox55 2 หลายเดือนก่อน

    Doesn't the func kinda defeat the purpose of the stats modifier? Only the specific type is determined by the class.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      The use of Func provides flexibility by allowing dynamic definition of operations without multiple subclasses, though it might make the relationship between operation and stat type less explicit. Perhaps in a future video we can enhance clarity by incorporating more specific modifier classes or adopting a strategy pattern.

    • @crazyfox55
      @crazyfox55 2 หลายเดือนก่อน

      @@git-amend I would love to see a video about balancing pickups. Because this is a good system so far but I'm not sure how full it would become once lots of pickups and stats are added.

  • @DamageSoftware
    @DamageSoftware 2 หลายเดือนก่อน +1

    This looks great! Thanks for sharing.
    One thing is bothering me though.
    I might be missing something, but don't you think it will be better if you somehow cache the calculated value so you don't need to calculate it each time that you access the property getter ?
    What if you need to access the Attack or Defense property getter each frame ? This means that the calculation will happen every time, even though it might not need to.
    What I am personally doing is I do the calculation only when I change the list of modifiers.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Thanks for the comment! Yes, a cache would be a good idea if you were concerned about performance, and easy to implement.

    • @crazyfox55
      @crazyfox55 2 หลายเดือนก่อน

      I asked TH-cam for a router example, and it says the stats need to be calculated in each frame if you add a stat modifier that increases or decreases over time. I bet there are still some calculations which could be chached.

    • @publiclag
      @publiclag 2 หลายเดือนก่อน

      @@crazyfox55 I'd probably add an event for modifiers to flag a stat type "dirty". If a stat is dirty when queried, it'll be recalculated, otherwise the cache is used.
      So a modifier that changes over time can mark its stat dirty each update.
      Worst case you'll get one recalculation per frame, which is still a win if the stat is used more than once per frame, and no loss if less often.

  • @Xezner
    @Xezner 2 หลายเดือนก่อน +1

    Hello, what app are you using when you create the diagrams you present in your videos?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      ExcaliDraw for Obsidian
      th-cam.com/video/o0exK-xFP3k/w-d-xo.html

    • @Xezner
      @Xezner 2 หลายเดือนก่อน

      @@git-amend Thank you mate!

  • @codeperson3475
    @codeperson3475 2 หลายเดือนก่อน +1

    Hi! Why did you chose EventHandler approach for PerformQuery? Instead of while loop that sums all modifiers results?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +3

      By choosing an EventHandler approach, the design adheres to principles of object-oriented design such as encapsulation, loose coupling, and separation of concerns, making the system more maintainable and flexible to changes. This approach typically results in a system that can evolve more easily over time as new requirements emerge or existing functionality needs to be adjusted. This is why the Broker Chain pattern evolved from a basic Chain of Responsibility pattern that you are describing.

    • @codeperson3475
      @codeperson3475 2 หลายเดือนก่อน

      @@git-amend thank you for your content and detailed respone ❤❤❤

  • @MrHussain99x
    @MrHussain99x 2 หลายเดือนก่อน

    Could this pattern be used in coherence with the strategy pattern? E.g. my player has ability strategies that are called when I press a button. They have cool down times and animations that play. And some of them have buffs/debuffs for stats, whilst others spawn in projectiles etc.

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Oh yes, absolutely. It's a good idea!

  • @Fyres11
    @Fyres11 2 หลายเดือนก่อน

    Look like a pretty good base to start. For example I got a really long debuff, but I find a potion to remove it immediatly, how could I do that?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Managing cancellation of specific debuffs would likely involve adding a bit more flexibility to the StatsMediator and StatModifier structure. We could add an identifier or use a specific characteristic (like a tag or type), then remove the first matching debuff that matches. We'll probably delve into these kinds of scenarios in next week's video.

    • @Fyres11
      @Fyres11 2 หลายเดือนก่อน

      @@git-amend Nice. Will watch for sure how you expand that Stats modifier.

  • @Fitz0fury
    @Fitz0fury 2 หลายเดือนก่อน

    How dare you release this AFTER i closed out my stats and modifiers todo list literally this morning... 😂

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      Awww sorry! Hope it was helpful nonetheless!

    • @Fitz0fury
      @Fitz0fury 2 หลายเดือนก่อน +1

      ​@@git-amend Unfortunately it is LOL. I doubt you remember but my first thread on the discord was about this exact issue. i was relatively close to having the solution you have here, but couldn't figured it how to make it more generic. the best i could do needed hand made event channels for every characters individual stats. you and amaree said something to the combined equivalent of "just do it how you know you can for now, and refactor later if you need to..". i literally just decided to retackle it on Saturday night. I had everything done except for accuracy and evasion by 7:37am Sunday. accuracy and evasion commit was 10:05am. i took my phone off focus mode and got my subscriber alert for " stats the easy way". the sheer odds of you dropping this video THREE MONTHS LATER exactly as i finish my stat rework! it literally made me drop a few curse words and laugh the second i read the alert. 😅

    • @git-amend
      @git-amend  2 หลายเดือนก่อน +1

      @@Fitz0fury Well, perhaps ironically, I think next week's video is going to be on the subject of Refactoring 😁

  • @Guywiththetypewriter
    @Guywiththetypewriter หลายเดือนก่อน

    how do you feel about replacing the get methods with a Dictionary

    • @git-amend
      @git-amend  หลายเดือนก่อน

      I think it's a good idea and a natural next step as the system evolves. In fact, I'm using a dispatch table in today's video for just that reason, but it's a Dictionary by Type to Action. Same concept and for the same reason.

    • @Guywiththetypewriter
      @Guywiththetypewriter หลายเดือนก่อน

      @@git-amend brill thought so.
      As a point btw I am currently starting work on a top down tycoon game in a tavern and was wondering if you have any suggestions for handling the logic for entities moving around.
      Gonna need a system where entities can move of their own decision making but also be influenced to do things by player input.

    • @git-amend
      @git-amend  หลายเดือนก่อน +1

      @@Guywiththetypewriter I think I might start with either a behavior tree or finite state machine for entity decision-making, which would allow the entities to perform actions based on their state and could also handle player inputs dynamically. Additionally, using the Nav Mesh could allow entities to navigate your environments autonomously as well as under player direction. I've been using the Nav Mesh Agents a lot lately for this reason - even in my last few videos - the agents can move using the nav mesh and behaviour tree AI to get around, but I can just add a simple point and click too with just a few lines so I can set destinations myself.

    • @Guywiththetypewriter
      @Guywiththetypewriter หลายเดือนก่อน

      @@git-amend cheers!
      So also something else which, I'll preface with the fact I'm a university lecturer for engineering before I come off too entitled 😅
      I don't know if it's cause I've spent too much time in Java but I have swapped out quite a few of the implementations in the mediator with interfaces, that then things like the modifiers inherit.
      I do this out of habit as I like to do my logic before my implementation. But thinking about it, it could be a unique way to teach these concepts
      I.e. define interfaces for all the major aspects of the technique first, dive straight into the mediator and have it handle just the interfaces, then build the components.
      That way for viewers there is full context as to how each individual part fits into the overall architecture.
      It comes from something I noticed through teaching a few years back, which is when you explain how each indvidiual brick is made, before showing the blueprints, it can be hard for students to see the house, if you get my meaning?
      Would love your thoughts on this approach.

    • @git-amend
      @git-amend  หลายเดือนก่อน +2

      @@Guywiththetypewriter All I'm going to say about that is that a) I agree it is the preferred approach in a classroom or workplace to help students and junior developers think in terms of systems. In my work as a software engineer, of course implementation always begins with interfaces. b) I've come to realize that TH-cam is not a traditional classroom or workplace, and the audience is not a group of aspiring software engineers who have implicit trust in me, the presenter. What resonates with my audience and keeps them from switching to watch something else is something that continues to evolve as I do as a creator, based on analytics and feedback, yours included of course!

  • @ryaz4704
    @ryaz4704 2 หลายเดือนก่อน

    I have just unknowingly created a stat system very similar to this. Except the modifier in mine has 2 types, the permanent one and the temporary one

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      Nice! I had considered separating them; in some cases it might affect gameplay a little bit because of the order they were applied. Something to consider anyway.

    • @ryaz4704
      @ryaz4704 2 หลายเดือนก่อน

      Oh wait, no. It's different. Hmm... I could use your "MarkForRemoval"

    • @ryaz4704
      @ryaz4704 2 หลายเดือนก่อน

      @@git-amend I have a "Priority" property in my stat modifier. It's so that I can calculate the ones with multiply operation first

    • @ryaz4704
      @ryaz4704 2 หลายเดือนก่อน

      @@git-amend Oh also, I made the something similar to MarkForRemoval in my code be virtual and separate the timer logic to stat modifier classes that are temporary

  • @arnesso92
    @arnesso92 2 หลายเดือนก่อน

    Which asset are those trees and rocks ?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      I think most of them came from BK Mountains, though I was messing around with Highland as well. I'll find both the links and add them to the description in a minute here.

  • @lizkimber
    @lizkimber 2 หลายเดือนก่อน

    where does ivisitor/ivisitable come from?

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      It was from an earlier video - I've added a copy to this repository for you:
      github.com/adammyhre/Unity-Stats-and-Modifiers/blob/master/Assets/_Project/Scripts/Stats/Visitor.cs

    • @lizkimber
      @lizkimber 2 หลายเดือนก่อน

      @@git-amend awesome thanks - i did search your git but couldnt find it there.. so appreciate it

  • @yanch.965su
    @yanch.965su 2 หลายเดือนก่อน

    Is it okay to not unsubscribe on event after subscribing on it

    • @git-amend
      @git-amend  2 หลายเดือนก่อน

      It is generally not okay to neglect unsubscribing from an event after subscribing because it can lead to memory leaks by keeping the subscribed objects from being garbage collected. Always ensuring that subscriptions are appropriately removed when no longer needed helps maintain optimal performance and resource management in your game.