For the life of me I cannot understand how to properly set this state machine up. I've been trying for over a week, I've come to the conclusion that I am mentally slow and this sucks. Even when I set it up somewhat properly the code I write has some conflictions. I can do literally everything else, modelling, animation, texturing, environmental design, storyboarding. This little state machine and this code is stopping me from making a cool game. Can anyone provide a solution to help me get the ball rolling on this project?

  • Jakerb
    I still think your conditionals are messed up.
    At the end of your video you have the actual code that you're using displayed.
    The first condition is:
    if Input.is_action_just_pressed("Attack"):

    Followed by:
    elif not Input.is_action_just_pressed("Attack"):

    That previous line is functionally equivalent to an else:
    Either you Just pressed Attack, so the first condition gets activated, or you did not just press attack, so the second condition gets activated.
    Those are the only two possibilities.

    If you are doing this check in your _process() function, then every frame either you just pressed attack, or you didn't.
    THIS IGNORES ANY OTHER INPUTS, like block, for instance.

    Every time it detects that you did NOT just press attack, it sets attack to false, sword return to true, and idle to true.
    This happens even if you are pressing the block input, because of how you set up the logic.

    Can you please comment out that entire "elif not Input.is_action_just_pressed("Attack"): " chunk and see what happens?

Been there.
What goes wrong with your state machine?

    packrat
    I think the problem is really with the code, which I deleted the other day after trying to translate youtube tutorials to my situation.

    I basically write:

    if Input.is_action_just_pressed("Attack"):
    		animation_tree ["parameters/conditions/swordswing"] = true
                    animation_tree ["parameters/conditions/swordreturn"] = true
                    animation_tree ["parameters/conditions/idle"] = false
    if not Input.is_action_just_pressed("Attack"):
                    animation_tree ["parameters/conditions/swordswing"] = false
                    animation_tree ["parameters/conditions/idle"] = true

    That code is not verbatim but I can get that action to work ok. The problem comes when I introduce the block animation into the script.
    I'll write:

    if Input.is_action_pressed("Block"):  #because I want to be able to hold the button
                   animation_tree ["parameters/conditions/block"] = true
                   animation_tree ["parameters/conditions/swordswing"] = false
                   animation_tree ["parameters/conditions/idle"] = false

    It will loop between the swordswing and swordreturn animation. I cannot understand how to make the code do what I want the actions to do. Thank you for reading.

      Hm. I touched a state machine maybe twice in my life, and I never used syntax like that. Give it some time and someone smarter than me will show up.

        Jakerb what file is this ? Seems that you're overriding parameters when Attack button is not pressed ?

          vexymous I'm using these true or false parameters based on a tutorial I watched. It seemed easy for me to understand at the time. If you know of a better way please direct me to that.

          vexymous

          Here's a video showing that the code here works. I'm just having trouble adding additional actions without it glitching out.

          2023-06-11-10-16-55.mp4
          2MB

            Jakerb It looks like you have some red errors in your debugger. If you post them, we may know what's up.

              packrat

              I don't anymore, just still having trouble with the block animation being played. I'm trying different things to get it to work right. Here's a video showing where I'm at currently.
              This is that error:
              W 0:00:01:0038 The parameter 'delta' is never used in the function 'process'. If this is intended, prefix it with an underscore: 'delta'
              <GDScript Error>UNUSED_PARAMETER
              <GDScript Source>enemy.gd:8

              2023-06-11-15-12-13.mp4
              4MB

                Jakerb yeah, it's bieng overwritten in the code somewhere, when it tries to switch to "block" state, something switching it back, to the "idle" state perhaps ?, You can start by removing this code:

                if not Input.is_action_just_pressed("Attack"):
                                animation_tree ["parameters/conditions/swordswing"] = false
                                animation_tree ["parameters/conditions/idle"] = true

                  From what I understand, you have two inputs you want to react to, attack and block.

                  In each case, we want to check if we can react to that input, transition to the associated animation if able, then return to the idle state to react to new inputs.

                  The code that vexymous pointed out reacts when you have NOT just pressed the attack input, which is different than reacting to a different, non-attack input.

                  I think you should only react to the inputs for attack and block directly, and the tree should handle resetting us to idle.

                  Edit: Try putting your "if not Attack just pressed" as an elif after the "if block is pressed" chunk.

                  We only want to reset to idle if we are not currently holding blocking.

                    stranger_anger

                    vexymous

                    I think the issue may be with the block animation. All of my other animations say imported animations. I must've only keyframed the block anim within godot. Also all of my other animations will play in the state machine except for block. Do you think having a mix of imported and godot native animations could interfere that way?
                    Also sorry we have to download the videos, wish there was an internal media player. Thank you for your help!

                    2023-06-12-16-37-55.mp4
                    4MB

                      Jakerb
                      I still think your conditionals are messed up.
                      At the end of your video you have the actual code that you're using displayed.
                      The first condition is:
                      if Input.is_action_just_pressed("Attack"):

                      Followed by:
                      elif not Input.is_action_just_pressed("Attack"):

                      That previous line is functionally equivalent to an else:
                      Either you Just pressed Attack, so the first condition gets activated, or you did not just press attack, so the second condition gets activated.
                      Those are the only two possibilities.

                      If you are doing this check in your _process() function, then every frame either you just pressed attack, or you didn't.
                      THIS IGNORES ANY OTHER INPUTS, like block, for instance.

                      Every time it detects that you did NOT just press attack, it sets attack to false, sword return to true, and idle to true.
                      This happens even if you are pressing the block input, because of how you set up the logic.

                      Can you please comment out that entire "elif not Input.is_action_just_pressed("Attack"): " chunk and see what happens?

                        stranger_anger


                        Thank you for explaining. I'm slowly starting to understand.
                        I have tweaked the code a little bit and trying to let the state machine do it's thing.
                        The block animation actually plays now and it seems like I can interrupt the attack
                        animation. I would like to achieve that both ways between block and attack.
                        I'm currently trying to get the block anim to stop looping like it does.
                        It should go into block position when button is held and back to idle when released.
                        Do you see any issues with my current setup?

                        stranger_anger

                        This is it! Sort of. I'll keep tweaking some options to achieve exactly what I'm going for.
                        To achieve this I added the same block anim in the state machine but played in reverse
                        and then in the code I added if block input is released, then block anim (reversed) = true
                        I am galaxies away from anything complete but this is a good stepping stone I think.
                        Sir or madam, thank you for your help!