Enemy stuck in hit animation/state after getting hit too fast

Godot Version

(Godot 4.4.1)

Question

Hey everyone,

I’m working on a 2D game. I have a bug where every time the enemy takes damage, it enters a Hit state and plays a hit animation. But if it gets hit again before that animation finishes (for example, by a fast attack or rapid projectile), it re-enters the Hit state immediately. This ends up putting it in a loop where it just keeps getting hit and never returns to its normal behaviour.

Code

extends State
class_name SnailHitState

@export var damageable: BaseDamageable
@export var dead_state: State
@export var dead_animation_name: String = "dead"
@export var return_state: State
@export var return_animation_name: String = "idle"
@export var hit_animation_name: String = "hit"
@export var animation_tree: AnimationTree
@export var animation_player: AnimationPlayer

func _ready():
	if animation_tree:
		animation_tree.active = true
		print("AnimationTree activated")

	if animation_player:
		animation_player.connect("animation_finished", Callable(self, "_on_animation_tree_animation_finished"))
		print("Connected to animation_finished signal")

func on_enter():
	print("Entered SnailHitState")
	if not damageable:
		print("No damageable reference")
		return

	print("Damageable health:", damageable.health)

	if damageable.health > 0:
		print("Character is hit but still alive")
		if playback:
			print("Playing hit animation:", hit_animation_name)
			playback.travel(hit_animation_name)
	else:
		print("Character is dead")
		if dead_state:
			print("Switching to dead state:", dead_state)
			emit_signal("interrupt_state", dead_state)
			if playback:
				print("Playing dead animation:", dead_animation_name)
				playback.travel(dead_animation_name)
		if character:
			character.set_direction(Vector2.ZERO)
			print("Character direction reset to Vector2.ZERO")

func state_process(delta: float) -> void:
	pass

func _on_animation_tree_animation_finished(anim_name: StringName) -> void:
	print("Animation finished:", anim_name)

	if anim_name == hit_animation_name:
		print("Hit animation completed")
		if return_state:
			print("Transitioning to return state:", return_state)
			if playback:
				print("Playing return animation:", return_animation_name)
				playback.travel(return_animation_name)
			emit_signal("interrupt_state", return_state)

Working Debug print output

Entered SnailHitState
Damageable health: 99989.0
Character is hit but still alive
Playing hit animation: hit
Animation finished: hit
Hit animation completed
Transitioning to return state: Follow:<Node#71772932997>
Playing return animation: idle

Broken Debug print output Example (Spammed Hits)

Entered SnailHitState
Damageable health: 99959.0
Character is hit but still alive
Playing hit animation: hit
Entered SnailHitState
Damageable health: 99949.0
Character is hit but still alive
Playing hit animation: hit
Entered SnailHitState
Damageable health: 99939.0
Character is hit but still alive
Playing hit animation: hit

Thank you!

Can you show where these print statements are being made? The current sample doesn’t seem to change states, so it isn’t likely the culprit.

Make sure to format code pastes properly

Hi there, thanks for taking interest in my issue. I have reformatted my post. Hopefully that helps!