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