How to use the Command Pattern (Skill Combos Example)

Поділитися
Вставка
  • Опубліковано 1 жов 2024

КОМЕНТАРІ • 56

  • @git-amend
    @git-amend  11 місяців тому +7

    Hi everyone! I mention Animancer PRO in this video - there is also a FREE version, link in the description for you. Enjoy! 😆

  • @cileth
    @cileth 11 місяців тому +10

    Learning so much with these tutorials! So rare to see tutorials thought out in a way that can easily scale up. Love it!
    If you need any ideas for things to make tutorials on...would be awesome to see how you would approach a save system, inventory/crafting system, quest system, tools for game designers, procedural animation / ik, multiplayer FPS, using unity netcode services (maybe unity would sponsor?). Have a general idea of where to start on these things but learning how an experienced developer would approach these problems and avoid spaghetti down the line is always helpful.

    • @git-amend
      @git-amend  11 місяців тому

      Thanks, all good ideas for future topics!

  • @TheKr0ckeR
    @TheKr0ckeR 10 місяців тому +4

    Aha, now i realize i could have used Command Pattern for match-3 game! After matching, lots of things happening, explosions, reordering, refilling board.. they might be all planned with command pattern!

  • @zerothehero.takeasip6612
    @zerothehero.takeasip6612 11 місяців тому +3

    Going to watch this video later but just wanted to say that I always felt crazy when I complained about the limitations unity’s mecanim to others as I would feel they would gaslight me into thinking I just didn’t know how to use it ( as if there even is much to learn, literally making tons of layers, blend trees and sub machine states to organize the mess) but glad to know someone of your background thinks the same. Imo the problem with mecanim isn’t the enforcement of the visual aspect (although I am not a fan) but rather how you are forced to interact with it’s FSM from the outside rather being able to do it from the inside. The Whole point of an fsm is to make the information easy to manage and you are literally forced to use parameters exclusively via string references to access animations which leads to a lot of code bloat. Animancer is cool but having to pay to use all the features always felt crappy to me imo (no shade on the creator, it just feels as though it should be a standard unity feature.)

  • @thekaribousband4151
    @thekaribousband4151 7 місяців тому +1

    Hey, that is a great video thank you !
    However, I'm quite confused about one thing : in this implementation, the view seems tightly coupled to the logic. What I mean by that is that the logic is waiting for the view to resolve. I would assume that this is the role of the command buffer, but I wonder how this would work in a turn-based game for example, or anything that relies on an MVC framework ? Thank you !

    • @git-amend
      @git-amend  7 місяців тому

      This video is about the programming pattern itself and not really about game architecture. You might be more interested in the more recent video about MVC/MVP with also uses the Command pattern: ua-cam.com/video/v2c589RaiwY/v-deo.html

  • @catpyjamas
    @catpyjamas Місяць тому

    Thanks for this. I got it to work, but I had a diff implementation. I wanted it to kick out of commands not based on duration, but on an animation event. I also did not want to have entity have all the methods in it, so through a bunch of inheritance and generics I'm not even sure how I set up, I got it so that I can just call whatever method I want for a particular command directly from the character class, which all the game's characters will inherit from. So no more entity, just "character", and the commands can be custom made for each character, there's no shared method pool in IEntity.
    It does require me to declare empty classes that fill in the "T" types for the generic base class though, not sure if that's great practice, but hey it works.

  • @anasmostefaoui3027
    @anasmostefaoui3027 11 місяців тому +3

    great video :D, I like the way you presented and implemented the pattern. Your channel should be one of the top channel in the game dev field.

    • @git-amend
      @git-amend  11 місяців тому +1

      I'm humbled by your kind words, thank you!

  • @manofapocalypse
    @manofapocalypse 9 місяців тому +1

    so for group of characters i should do
    List to have list of actually selected characters
    Queue to queue commands for all of them or maybe i should do something like Queue
    MoveCommand that would take Vector3 to order them to move to given position
    so it would work like in Baldurs Gate 3?

    • @git-amend
      @git-amend  9 місяців тому +1

      That sounds like a good approach to have some Baldur's Gate 3 type behaviour. With a Command, you typically encapsulate all the information required to execute the command within the command itself - that way you can pass the command around like an object and execute it from anywhere, anytime. Since you've probably selected the character and the destination before adding the Command to your queue, you would encapsulate that information into the Command. You could create a MoveCommandFactory that accepts a Character and a Vector3 and returns you a ready to use Command. Or you could also use a static factory method inside the MoveCommand class that does the same thing.

    • @manofapocalypse
      @manofapocalypse 9 місяців тому +1

      ​@@git-amend something like this?
      public class MoveCommand : ICommand
      {
      private Character character;
      private Vector3 destination;
      public MoveCommand(Character character, Vector3 destination)
      {
      this.character = character;
      this.destination = destination;
      }
      public static MoveCommand CreateMove(Character character, Vector3 destination)
      {
      return new MoveCommand(character, destination);
      }
      public override async Task Execute()
      {
      character.Move(destination);
      // I don't know how should i use here await
      }
      }

    • @git-amend
      @git-amend  9 місяців тому +1

      @@manofapocalypse Yes, this looks like a good start. To execute the MoveCommand asynchronously, you would typically have the Move method in the Character class return a Task. This way, you can await the completion of the movement. Assuming Character.Move is an async method, the implementation would look like this:
      public class MoveCommand : ICommand{
      // ... existing code
      public override async Task Execute() {
      await character.Move(destination); // Assuming Move is an async method
      }
      }
      // Usage in Queue context
      Queue commandQueue = new Queue();
      // Add commands to the queue
      commandQueue.Enqueue(MoveCommand.CreateMove(someCharacter, someDestination));
      // Executing commands
      while (commandQueue.Count > 0){
      var command = commandQueue.Dequeue();
      await command.Execute(); // Execute each command asynchronously
      }

    • @manofapocalypse
      @manofapocalypse 8 місяців тому

      @@git-amend again my comments were hidden by youtube

  • @BrandonHan-l1l
    @BrandonHan-l1l 7 місяців тому

    Awesome stuff! I've been leveling up so much recently from your content, thank you!
    How would this system hold up if the player were to pause in the middle of a command, e.g. half way thru a spin?

    • @git-amend
      @git-amend  7 місяців тому +1

      Thanks! That’s an interesting problem to solve, and I would have to give it some thought . It depends a little bit on how the pause is implemented I suppose.

  • @Sevrc1136
    @Sevrc1136 2 місяці тому

    so quick question. bwtn this and the strategy pattern, is the only real difference that with command you can pass the functionality you create to other entities or really where ever you want? so strategy is used just for that single entity? (Hope this makes sense, still trying to learn all the amazing things youve put on you channel)

    • @git-amend
      @git-amend  2 місяці тому +1

      Yes, your understanding is correct. The main difference is that the Command pattern encapsulates functionality as an object, allowing it to be passed around and executed by different entities, while the Strategy pattern is used to define a family of algorithms and make them interchangeable within a single entity. The Command pattern provides more flexibility in terms of reusability and decoupling actions from the invoker.

  • @Cloud-Yo
    @Cloud-Yo 7 місяців тому +1

    Like my great-great-grandpappy used to say, a git-amend a day keeps the git-blame away...Command pattern, check!

    • @git-amend
      @git-amend  7 місяців тому +2

      Don't forget you can also blame someone else:
      git commit --amend --author=" " --no-edit

  • @baselpro5228
    @baselpro5228 11 місяців тому +1

    Love your videos man.
    Now that's what i would like to see and hopefully for other videos to come , A concert example with Design patterns on Unity even if with just cubs.

    • @git-amend
      @git-amend  11 місяців тому +1

      Thanks! Yes, more to come!

  • @TheKr0ckeR
    @TheKr0ckeR 2 місяці тому

    How could we improve this if the user is clicking 3 in a row, and start a skill combo? For example in Tribes of Midgard game, when we spam mouse, it will create a attack combo like right, left and front. But at some point it stops, what i mean is, If we constantly add this attack requests to command, even if the player is in 3. attack and we spammed like 15 times, they will be added and player will be attacking a lot of time when he released mouse, How do developers balance that? For example, every attack runs like 0.5 seconds, and player is spamming mouse to attack, we added we added, we added, player spammed like 10 times but we it should stop at some point, how we should decide where to stop. I hope i expressed enough about that.

    • @git-amend
      @git-amend  2 місяці тому +1

      It's hard to give implementation details in YT comments without collaborating on an actual project, but one way to balance attack combos when a player spams the attack button is to use asynchronous methods and cooldown timers. This involves creating a combo sequence with defined attacks and managing the timing between them. When a player attacks, the combo starts, and the game records the attack time. Asynchronous methods ensure a cooldown between attacks. If the player clicks again within a set period, the combo advances; otherwise, it resets after a maximum duration. This prevents indefinite attack queuing while avoiding excessive attacks from spamming.

    • @TheKr0ckeR
      @TheKr0ckeR 2 місяці тому

      @@git-amend Sounds great explanation. Thats what i needed thanks. We can even stop adding at some point if its too much.

    • @TheKr0ckeR
      @TheKr0ckeR 2 місяці тому

      @@git-amend Especially the point wherr you talked about it resets after max duration. good idea

  • @Hazzel31337
    @Hazzel31337 5 місяців тому

    i could imagine this pattern in a auto battler where the player arranges the commands and than they fight each other

    • @git-amend
      @git-amend  5 місяців тому

      Yes, very useful for that kind of thing.

  • @nightonmars
    @nightonmars 9 місяців тому

    Thanks a bunch for your videos. It's quite difficult to find tutorials that look at code organisation in a game (or any app), which is so useful! Even though quite a bit of it is way above my head... But wax on wax off and I'll master the crane one day. 🤣

    • @git-amend
      @git-amend  9 місяців тому +1

      Great, thanks for watching! Lots more to come!

  • @metaling278
    @metaling278 6 місяців тому

    Is there a public github repo for this?

    • @git-amend
      @git-amend  6 місяців тому +1

      No, there is not.

  • @SirSone7
    @SirSone7 11 місяців тому

    thanks a lot for all these guides for design patterns, so much has learned thanks to you!
    I wonder if you don't have ideas ahead for more guides, could you make a guide example for DOTS ECS .. i've been really trying to learn it but no success and there aren't any updated guides that are easy to understand like you explain things
    Waiting for more content ahead!

    • @git-amend
      @git-amend  11 місяців тому

      Thanks! And thanks for the comment. I will certainly keep DOTS in mind as something to dive into in the future. My favorite game was actually built in part using Unity DOTS - V Rising.
      blog.stunlock.com/v-rising-dev-update-4-v-rising-engine-and-cutting-edge-technology/

  • @trell_7842
    @trell_7842 11 місяців тому +1

    Nice example, thx for video!

    • @git-amend
      @git-amend  11 місяців тому

      Glad you liked it!

  • @MarushiaDark316
    @MarushiaDark316 11 місяців тому

    I've heard that using Task async can cause problems in an actual built game, as opposed to coroutines. Do you know if there's any truth to that? You clearly operate at a high level and can communicate complex concepts rather eloquently, so would be useful to see you do a full video explaining the entire Task async workflow and when to use it, as well as other oft-unspoken topics like IEnumerator.

    • @git-amend
      @git-amend  11 місяців тому +1

      There is some truth to that - it used to be that it was problematic to use an async (Task) workflow for WebGL Builds. The new Awaitable class overcomes that particular issue. That's a good idea for a future video, I'll put it on the list! Thanks.

  • @hamsterhaunter5718
    @hamsterhaunter5718 11 місяців тому

    I'm wondering why you are sticking with Unity and not switching to other game engines after the things that's been happening to Unity.

    • @git-amend
      @git-amend  11 місяців тому +3

      I expect Unity to course correct, particularly with the CEO transition underway. In the meantime, and likely for several more videos, I'll be focusing on topics like programming patterns applicable to any modern programming language and not on features or systems tightly coupled to Unity.

  • @Broudy001
    @Broudy001 11 місяців тому

    Another fantastic tutorial, trying to get my head around how I'd use this in a dynamic combo system, that is you are part way through attack and if you time the next input correctly it does the next one in the combo. I probably need to build it and play with it first

    • @git-amend
      @git-amend  11 місяців тому

      Thanks! That's another level of complexity for sure! I can imagine a few different ways, but I think you are right - the best way to do it would be to dogfood a prototype. Maybe the Commands could be represented as a graph if an attack could be the start of several different combos.

  • @Sticks_Dev
    @Sticks_Dev 11 місяців тому

    Hi, I'm still very new to your content, as I only discovered you last night. Did a quick binge of all the programming patterns and I'm curious if there's any specific reason you didn't use a scriptable object for commands? Is that just because each command would only have a single instance of itself or is there some other reason?
    I imagine using scriptable objects to hold the commands would make it a lot more friendly to newer developers. I'm particularly interested in using this pattern for a time management game where each work station could have it's own command. Then, each workstation command could have it's specific command implementation decided in the inspector (if using scriptable objects it's just a drag and drop, otherwise it could be a serialized enum and a switch statement to set the command).
    Correct me if I'm wrong or if that isn't a great way to implement the pattern for that specific use case (or maybe there's a different pattern that would work better)? Either way, loving your content and it was an instant subscription.

    • @git-amend
      @git-amend  11 місяців тому

      Hello and welcome! The approach in the video was to demonstrate the command pattern in the context of a question another viewer had. If you don't need the flexibility of changing the commands at runtime and just want to set them "one and done" in the inspector, then our idea of using ScriptableObjects for commands in Unity, especially for a more visual and intuitive setup in a time management game, has merit. Your alternative suggestion of using a serialized enum also has merit but may lack the ease-of-use that ScriptableObjects offer. There is always more than one way to go about implementing a solution - some are just more flexible than others. The more you have to link up dependencies and references, the harder your game will be to change or expand - just keep that in mind. Another approach would be to use a Factory to supply the commands you want as needed. Glad you're enjoying the content and finding it insightful!

    • @Sticks_Dev
      @Sticks_Dev 11 місяців тому

      @@git-amend Thanks for the response, I always forget that there are different use cases for different implementations. I had just spent the last year working on a Unity Package for reusable code covering essential features like inputs (in the new input system with each input action on a scriptable object) that's reusable in every project, so I forgot that sometimes an implementation is specific to the game being made. I greatly appreciate your detailed response and quick feedback on my implementation ideas as I'm just about to begin my capstone university project and wasn't sure if the command pattern could work well for it.

  • @STARmod
    @STARmod 11 місяців тому

    Legend, you are legend my guy.

  • @kkh0101
    @kkh0101 11 місяців тому

    your channels is fascinating. thank you.

    • @git-amend
      @git-amend  11 місяців тому

      So nice of you, thanks!