0

I had a script somewhat similar like in this video:

extends KinematicBody2D

var movement=Vector2(); 
var up= Vector2(0, -1); 
var speed=200;
var isAttacking=false; 

func _process(delta): 
    if Input.is_action_pressed("ui_right") && isAttacking == false:
        movement.x = speed;
        $AnimatedSprite.play("walk"); 
    elif Input.is_action_pressed("ui_left") && isAttacking == false: 
        movement.x= -speed;
        $AnimatedSprite.play("Walk"); 
    else: 
        movement.x = 0; 
        if isAttacking == false: 
            $AnimatedSprite.play("Idle"); 
    
    if Input.is_action_just_pressed("Attack"):
        $AnimatedSprite.play("Slash");
        isAttacking=true; 
    movement = move_and_slide(movement, up * delta); 
    
func _on_AnimatedSprite_animation_finished():
    if $AnimatedSprite.animation == "Slash": 
        isAttacking= false; 

but the problem was when I was rapidly pressing attack & movement on my keyboard
sometimes the isAttacking did not get set back to false after the animation was completed and hence froze my character animation

Maybe it was a bug in invoking the connected signal function when pressed rapidly? but anyhow it gave me a nightmare

so I came up with this workaround for rapid key pressing attack and movements (check the solutions) so no one else has to go through what I did :)

cak3_lover
  • 1,440
  • 5
  • 26

1 Answers1

0

Instead of checking for attack in _process() I used _unhandled_key_input() and this seemed to get rid of the problem

Hope this helps! :D

...

func _process(delta): 
    if Input.is_action_pressed("ui_right") && isAttacking == false:
        movement.x = speed;
        $AnimatedSprite.play("walk"); 
    elif Input.is_action_pressed("ui_left") && isAttacking == false: 
        movement.x= -speed;
        $AnimatedSprite.play("Walk"); 
    else: 
        movement.x = 0; 
        if isAttacking == false: 
            $AnimatedSprite.play("Idle"); 

    if Input.is_action_just_pressed("Attack"):
        $AnimatedSprite.play("Slash");
        isAttacking=true; 
    movement = move_and_slide(movement, up * delta); 


func attack_animation_finished(var _extra):
    isAttacking=false
    
func _unhandled_key_input(event):
    if(event.echo):
        return
    
    if(!event.pressed):
        return
    
    if(event.scancode==KEY_X and !isAttacking): # x key to attack (you can use whatever you like)
        isAttacking=true
    
        if!($AnimatedSprite.is_connected("animation_finished",self,"attack_animation_finished")): 
            $AnimatedSprite.connect("animation_finished", self, "attack_animation_finished", [], CONNECT_ONESHOT) # warning-ignore:return_value_discarded
        $AnimatedSprite.play("Slash");

Note: I haven't ran this particular code segment but I have used this logic/approach in a working larger script which would be too long to share here

cak3_lover
  • 1,440
  • 5
  • 26
  • It is unlikely but `_process` can miss inputs (in which case `is_action_just_released` will return `true` but you never saw `is_action_just_pressed` or `is_action_pressed` return `true`). On the other hand, since you are driving this by the animation, did you try checking which is the current animation instead of using a variable to keep track of it? - **Note** You can check `is_action`, `is_pressed` and `is_echo` if you rather not hard code the `scancode`. See: https://stackoverflow.com/a/69982843/402022 – Theraot Dec 16 '22 at 11:17
  • @Theraot I did use `is_action_just_pressed("Attack")` in the original question code but it doesn't register when pressing the keys quickly and I don't understand what the use of `is_action_just_released` would be in changing the `isAttacking` variable? even if I did release the attack key I still want the attack animation to complete all the way before changing `isAttacking=false` and as for "variable to keep track of it" it's just cleaner, faster & more versatile overall (as far as I can tell) oh and I just used the `scancode` just to keep it simple but `is_action` is better yes – cak3_lover Dec 16 '22 at 12:55