Debugger keeps giving error because of an animation_finished signal

Godot Version

4.4.1

Question

New to Godot and programming. Was following a tutorial that used a state machine for the player. My issue is that in the attack state. When the player enters that state the animation updates and a signal for animation finished is connected to a method to set the attacking to false. I also have a _can_attack bool that if false returns from the enter state. The issue is that i keep getting an error.

E 0:00:00:959   AttakcState.gd:28 @ Exit(): Attempt to disconnect a nonexistent connection from 'AnimationPlayer:<AnimationPlayer#37832623459>'. Signal: 'animation_finished', callable: 'Node(AttackState)::EndAttack'.
  <C++ Error>   Condition "signal_is_valid" is true. Returning: false
  <C++ Source>  core/object/object.cpp:1525 @ _disconnect()
  <Stack Trace> AttakcState.gd:28 @ Exit()
                PlayerStateMachine.gd:37 @ ChangeState()
                PlayerStateMachine.gd:11 @ _process()

This is my attack state code

class_name AttackState extends State

@export var speed : float = 200
@export var accl : float = 2.0

@onready var walk: WalkState = $"../Walk"
@onready var idle: IdleState = $"../Idle"
@onready var animation_player: AnimationPlayer = $"../../AnimationPlayer"
@onready var sword: Sword = $"../../WeaponSpawn/Sword"

var attacking : bool = false
var _can_attack : bool = true



func Enter() -> void:
	if _can_attack == false:
		return
	player.UpdateAnimation("attack")
	animation_player.animation_finished.connect(EndAttack)
	attacking = true
	AttackCoolDown()
	
	
func Exit() -> void:
	animation_player.animation_finished.disconnect(EndAttack)
	attacking = false

func Process(_delta : float) -> State:
	player.velocity = Vector2.ZERO
	print(attacking)
	
	if attacking == false:
		if player.direction == Vector2.ZERO:
			return idle
		else:
			return walk
	
	return null
	
func Physics(_delta : float) -> State:
	return null
	
func HandleInput(_event : InputEvent) -> State:
	return null
	
func EndAttack(_anim_name) -> void:
	attacking = false
	
func AttackCoolDown() -> void:
	if _can_attack:
		_can_attack = false
		await get_tree().create_timer(sword.Cooldown()).timeout
		_can_attack = true

All the code regarding the weapon and cooldown is mine and not part of the tutorial pretty sure that is where the problem is.
Thanks

The error message means that this signal cannot be disconnected from EndAttack because it currently isn’t connected. I presume Enter is called when the state is entered, and Exit is called when the state is exited.

Enter does connect animation_finished to EndAttack, but not necessarily always:

func Enter() -> void:
	if _can_attack == false:
		return

If _can_attack is false when Enter is called, this early return will prevent animation_finished from getting connected, and can therefore not be disconnected.

You can use is_connected to verify if a connection already exists before calling disconnect.

2 Likes

Thanks that worked.

1 Like