Advanced state machine techniques in Godot 4

แชร์
ฝัง
  • เผยแพร่เมื่อ 5 มิ.ย. 2024
  • Here's a look at some more advanced techniques you can implement in your state machine when you need something a bit more complex than the starter state machine I showed in the last video. We'll look at three techniques worth understanding for building out the state machine you need and address a few common pain points people run into when programming a state machine.
    Text version with code snippets: shaggydev.com/2023/11/28/godo...
    Sample project: github.com/theshaggydev/the-s...
    00:00 Dependency injection
    02:50 Composition
    07:15 Hierarchical state machines
    09:25 How to do multiple things at once
    10:30 Sharing data between states

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

  • @itisjams
    @itisjams หลายเดือนก่อน +4

    This video is magical. You've just answered all of the state machine related questions I haven't found good answers to in one go, thanks so much!

  • @BradyHenry
    @BradyHenry 6 หลายเดือนก่อน +13

    couldn't be more perfect timing on this video

  • @godotgamelab
    @godotgamelab 6 หลายเดือนก่อน +14

    It's such a great video, top-quality content as always. I especially appreciate providing the text-based version.
    It must be a ton of work to design, write and edit this kind of content.
    I just wanted to let you know that you actually inspired me to start my own tutorial channel! :)
    Keep up the good work. Cheers!

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

      Thanks so much!! Watched your first video and it was really good! You've already figured out how to make the architecture bits more interesting than I have 😅 Good luck with your channel, though based off of what I've seen I'm sure you'll do great!

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

      @@TheShaggyDev Thanks man, I REALLY appreaciate you for taking the time to answer and watch my video! You are even more cool than I though. Thanks again!😁

    • @nandomax3
      @nandomax3 6 หลายเดือนก่อน +1

      i'd like to suggest the creation of a discord server where game devs who likes clean code and good architecture can could home :)
      On my daily life I'm a senior backend developer and I'm really missing a community with a more advanced approach to code

  • @Chaff_Games
    @Chaff_Games 5 หลายเดือนก่อน +3

    I've been working on an FPS template for ages and I use a concurrent state machine. A state machine that's just dedicated to movement and another to controlling the active weapon, shooting ect.

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

    Exactly what I was waiting for, right on time too. Was just about to start a Game Dev session.

  • @ponderingpermanence8095
    @ponderingpermanence8095 6 หลายเดือนก่อน +1

    Your videos are always a delight, thanks man!

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

    Incredible stuff. Thank you!

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

    Answered some of the remaining questions I had about state machines. Thanks!

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

    The tips at the end are gold tips! Thank you for the amazing tutorial :D

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

    such a great video, thankyou for all the info :O it so much easier to understand now !

  • @simonscharlachrot7960
    @simonscharlachrot7960 6 หลายเดือนก่อน +3

    clear and concise, thanks!

  • @dustingarner4620
    @dustingarner4620 6 หลายเดือนก่อน +1

    This is great, thank you!

  • @finestcustard5647
    @finestcustard5647 6 หลายเดือนก่อน +1

    This is awesome! A lot of this flew over my head as I'm pretty new to game dev, but overall I was still able to follow. I also really appreciate the book recommendations at the end!

  • @Tubulin_
    @Tubulin_ 5 หลายเดือนก่อน +1

    Your videos on state machine are great! Would love further videos delving into the topic of state machines!

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

    gah - thank you for this video... i've been exhausting myself trying to learn more about godot-specific approaches to solving a number of the issues/challenges you mention here

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

    11:32 this game actually looks fkn cool!

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

    Great!

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

    This tutorial is absolutely fantastic, and I've learned a great deal from it. Thank you very much for sharing your knowledge. I have one observation regarding the "move_component". I noticed that while you've declared types for all parameters and variables, the "move_component" was an exception. Would it be possible to encapsulate these functionalities in a class like "MoveController"? This class could include fundamental methods such as "get_move_direction()", "wants_to_jump()",... In "CharacterBody2D", you might then add a node with a new script titled "PlayerMoveController" that inherits from "MoveController" and overrides certain functions. Within "PlayerMoveController", you could manage controller inputs, and in NPCs, automate certain behaviors. Ultimately, this approach would allow for the specific type declaration for "move_component" using "MoveController", enhancing the robustness and readability of the code.

    • @TheShaggyDev
      @TheShaggyDev  8 วันที่ผ่านมา

      Yep! You could certainly set this up in such a way as to have typed support all throughout, such as via the method you've mentioned here. I think overall that's a good idea, and it's something I'd normally do. The only reason I didn't do it here is that the move component is so simple, and I find that too much boilerplate can sometimes throw people for a loop.

  • @UhGoomba
    @UhGoomba 5 หลายเดือนก่อน +1

    I watched your other state machine videos months ago and I honestly didn't like the implementation. But I'm glad I came back, I didn't realize this was new, and I was actually making a similar input thing for my game.

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

      Thanks for checking it out again! Part of the reason I wanted to revisit the subject for Godot 4 is that, in retrospect, I also felt the original videos were a bit lacking. Still plenty of options in how to make a state machine, but I wanted to make something more comprehensive than before if going for the node-based approach presented here.

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

    Great explanation! How do you feel about state charts, and more specifically, the state charts extension available on the Godot asset library?

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

      I'm not too familiar with state charts, but from a quick glance at the site, they look interesting, so could be worth trying out. I'm also not very picky about how you handle state management so if it works then go for it!

  • @Max-gm2un
    @Max-gm2un 6 หลายเดือนก่อน

    So much great information, thanks for the very good video! I have a question: So I've exported variables, friction, acceleration and speed in the walk state. Now I also want to move horizontally while I am in the jump State. Do I have to copy the export variables from the walk state script and paste them to the jump State script and type the exact numbers in to the inspector. Same also for the Fall State. I also found myself copying the function for moving horizontally from the walk state to the jump and fall state.
    Is there a better solution for this? Thanks in advance for the answer!

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

      Hmm, if it's just variables that need to be shared, you could try the data store technique to make that available multiple places. If you have code as well, could be a case to go hierarchical and define a move state that the others inherit from that can share the relevant code with any state that needs it.

    • @Max-gm2un
      @Max-gm2un 6 หลายเดือนก่อน

      ​@@TheShaggyDevThank you for your help! I'm gonna try that

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

    I personally came up with the idea of having shared functions being implemented into the state machine. It's easily accessible, often specific to the very object the machine is attached to.
    A component system as mentioned in your video would be the next step for that, especially usefull for re-useable code parts or when it becomes "too much".
    The inheritance approach I would stay away from. Not only is it more obfuscating, as you need to go down the hierarchy tree to check up on the function you want to call, it also becomes a real headache if multiple objects want to use the same components/system, but differ widely otherwise. On top of that, generally speaking, inheritance seem to be pretty bad for performance, according to numerous videos on TH-cam. Though I do not know exactly how bad it is and if it holds true in Godot's case (though I very much assume it still is).

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

      those would be symptoms of a poorly set up inheritance structure, not problems with inheritance itself. the indirection / lookups imposed by inheritance is trivial for the purposes of game development

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

    Hello, I was playing with your state machine Implementation from the first video and I used Godot Resources to inject my movement logic. For example, I have a walk resource that contains some exported vars for walk acceleration, max walking speed, input reading and the logic to apply acceleration and friction. I inject this resource on the fall state, walk state and jump state so the player can move on the X axis during those states. I can record a video explaining it if you want, it's a component driven development I saw here on youtube. When I changed my script to handle the enemy's states, I created a new walk handler for the npc called wander_handler that applies constant Velocity in one direction until a collision happens.
    So I have two walk_handlers that extends the Walk resource and I can inject them as I see fit. This way I can create two players with the same base scene and make you of them respond to keyboard wasd and the other to arrows or AI.
    P.s. in my state machine Implementation I try to keep the states implementation unique per context. My player and my enemy shares the state machine object and base state. But each one will have a different node for walk or idle. My enemy just walks around and fall, it has no jump. It moves a little wait for a few seconds, move again. If is on wall it changes direction. If I want to use this state graph to other enemy, I can use the movement component to change it's brain. Or if it's going to be super different I prefer to create new states from the base state to avoid coupling

    • @TheShaggyDev
      @TheShaggyDev  6 หลายเดือนก่อน +1

      Thanks for sharing the follow up to your last comment! I really like the technique you've developed. Using Resources makes a lot of sense and I like how you've organized everything.

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

    I would like to know how do you deal with signals to implement hitboxes and hurboxes. I'm creating the sword attack for the main char I need to implement the hitbox for the sword and the hurtbox for the enemy.
    I did it with the same component based approach, I created a hurtbox scene that is just an Area2D with the attribute damage and group "has_damage" and created a hurtbox scene that is just an Area2D with the group "has_health" that holds the max health and current health.
    To connect it to the state machine and trigger state changes when I hit an enemy, I had to extend the state machine base class to have also the process_area_signal(area: Area2D) -> void and the state base class to have the matching func process_area_signal(area: Area2D) -> State. And now when I hit the enemy, the original signal _on_area_entered(area: Area2D) calls my enemy's state_machine.process_area_signal(area) and trigger the death state or damage state.
    I don't know if this would be the best approach, I'd to hear more about you and how do you deal with signals and state machines
    Do you have a discord server?

    • @TheShaggyDev
      @TheShaggyDev  6 หลายเดือนก่อน +1

      My approach in the past with signals has been to let the parent object listen and then pass that information down to the state machine, whether with a direct state change or calling a function somewhere, usually because for something like a hurtbox I probably need to manage health, potential s, etc that may need to work outside of the state machine.
      I'm afraid I don't have a Discord server. May get around to that one of these days...

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

    Hi, been trying to implement this in my own project but it's a top-down game and I couldn't figure out how you would detect which of the 4 animations (top, down, left and right) to play for each state

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

      Hmm, I'd probably track the orientation in a shared data store that each state can update as appropriate and then name the states in the form "orientation_animation", or something like that. Then, the enter function can be updated so that it plays the animation name given to it, but prepends the orientation to the animation name.
      Just one way of doing it.

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

    Hey. I'm having an issue when I have multiple instances of an object, and when one of the state's emit a signal, every instance reacts to it. Any general thoughts why that could be? I recall there being an inspector setting for this, but can't remember where I heard it. Thanks for the video!

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

      Hmm, I'm not 100% certain. Are the signals connected via the editor or via code?

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

    Would it not be easier and more powerful to just use the AnimationTree state machine with advanced conditions/expressions?

    • @TheShaggyDev
      @TheShaggyDev  4 หลายเดือนก่อน +1

      Could give it a go and see how it works! I don't find myself using AnimationTree very often, and what I've presented here is a more generic approach.

    • @TheOnlyGhxst
      @TheOnlyGhxst 4 หลายเดือนก่อน +1

      @@TheShaggyDev I’m using the animationtree in my current project which is why I was wondering. It’s actually extremely powerful.

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

    get error "Invalid call. Nonexist fynction 'init' in base 'Node'"

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

      Whichever node is giving you this error, make sure it has the appropriate script attached.