0 votes

Hello,

I'm working on a simple sidescroller (Godot 3.2.2) and have created an enemy character. He has an animation for idle, walking, and taking damage, which I prepared using the AnimatedSprite node. I want his animation to switch to "damaged" every time his hitbox overlaps with the player's sword, but it seems the animation won't play, even though the signal works.

In my _physics_process code, I have the following. As you can see, I have created three states corresponding to the type of action.

match state:
    IDLE:
        velocity = velocity.move_toward(Vector2.DOWN * GRAVITY, ACCELERATION * delta)
        animatedSprite.play("idle")
        seek_player()
    CHASE:
        if player != null:
            direction = (player.global_position - global_position).normalized()
            velocity = velocity.move_toward(Vector2(MAX_SPEED * direction.x, GRAVITY), ACCELERATION * delta)
            animatedSprite.play("walk")
            animatedSprite.flip_h = velocity.x < 0
        elif player == null:
            state = IDLE
    DAMAGED:
        print('ouch!')
        velocity.x = 0
        animatedSprite.play("damaged")
        seek_player()

move_and_slide(velocity)

Here is my seek_player() function and the signals I'm using to manage the states:

func seek_player():
    if player != null:
        state = CHASE
    else:
        state = IDLE

func _on_HurtBox_area_entered(area):
    state = DAMAGED

func _on_HurtBox_area_exited(area):
    state = IDLE

func _on_PlayerDetection_body_entered(body):
    player = body 

func _on_PlayerDetection_body_exited(body):
    player = null

Basically, if the enemy sees the player, he will start walking. If the player escapes his view, he will be idle. Finally, if the enemy is hit with the sword, he will appear to take damage. But while the DAMAGE state runs (I see the print statement "ouch!" in the console), the animation never plays.

But if I remove the play("walk") line from the CHASE state, the "damaged" animation plays as expected - however, the enemy can no longer walk.

I've been trying to figure this out over the last few days and can't tell if I'm missing something simple or what! I'd appreciate any help! Let me know if you need more context.

in Engine by (15 points)

1 Answer

+1 vote
Best answer

Okay, so I think what your problem is that the DAMAGED animation does play, but it gets replaced immediately by another state (CHASE). On the first frame that the enemy gets hurt, it plays the correct animation. Then the seek_player function sets its state to CHASE, so in the next frame, the "walk" animation plays. My suggestion is to defer calling the seek_player() function again until the animation is done playing, or if you want the enemy to still move when hurt, handle animations separately from movement.

by (7,338 points)
selected by

Ahh, you're exactly right! I just added a yield(animatedSprite, "animation_finished") after animatedSprite.play('damaged') and that did the trick! Thanks a lot! I was scratching my head over this since Friday haha :')

I think the reason I thought the animation simply wasn't playing is that I added an animation_finished signal that never triggered. But of course it wouldn't trigger if only the first frame plays!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.