Unable to transition between AnimatedSprite animations

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By mashiyatz


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:
		velocity = velocity.move_toward(Vector2.DOWN * GRAVITY, ACCELERATION * delta)
		if player != null:
			direction = (player.global_position - global_position).normalized()
			velocity = velocity.move_toward(Vector2(MAX_SPEED * direction.x, GRAVITY), ACCELERATION * delta)
			animatedSprite.flip_h = velocity.x < 0
		elif player == null:
			state = IDLE
		velocity.x = 0

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

func seek_player():
	if player != null:
		state = CHASE
		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.

:bust_in_silhouette: Reply From: exuin

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.

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!

mashiyatz | 2020-10-04 12:46