Platform fighter bug

Godot Version

4.4.1

Question

I’m making a platform fighter (beginner here, just trying to refine my skills), and I’m currently making my first fighters grounded attacks. I have animations for his jab and up tilt, and the jab works perfectly fine. However, whenever he performs his up tilt, it loops infinitely and will not stop until he moves. I have no clue as to why it does this, and am just looking for some input on this.

Here’s the code pertaining to the attacks:

#manage input directions
	if abs(h_input) > abs(y_input): #x_input
		if h_input > 0:
			input_dir = 'r'
		elif h_input < 0:
			input_dir = 'l'
	elif abs(y_input) > abs(h_input): #y_input
		if y_input > 0:
			input_dir = 'u'
		elif y_input < 0:
			input_dir = 'd'
	elif (abs(h_input) == abs(y_input)) and (h_input * y_input != 0):
		if h_input > 0 and y_input > 0:
			input_dir = 'ur'
		elif h_input < 0 and y_input > 0:
			input_dir = 'ul'
		elif h_input > 0 and y_input < 0:
			input_dir = 'dr'
		elif h_input < 0 and y_input < 0:
			input_dir = 'dl'
	else: #neutral input 
		input_dir = 'n'
#implement the functions that handle attacking
	if is_on_floor():
		if Input.is_action_just_pressed(attack):
			if input_dir == 'u':
				if state != States.attack:
					u_tilt()
			
			elif input_dir == 'n':
				if $AnimatedSprite2D.frame == 24 or $AnimatedSprite2D.frame == 25 or $AnimatedSprite2D.frame == 26:
					jab_2()
				else:
					if state != States.attack:
						jab_1()
func u_tilt():
	state = States.attack
	velocity.x = 0
	$AnimationPlayer.stop()
	$AnimationPlayer.play("u_tilt")
	await $AnimationPlayer.animation_finished
	state = States.idle

In addition to this code, the fighter runs on a state machine, and the states in question are States.attack, States.idle, and States.run.

Any input? I really am completely clueless as to what is happening or why the issue is happening. The code for his jab is identical to the code for his up tilt, except for the animation name, and it works exactly as intended.

If there are any suggestions to make this code more efficient as well, I would appreciate them, but I mainly just want to resolve this issue.

I think the $AnimationPlayer.animation_finished signal is not being emitted for looping animations, so your state is never being set back to idle.
Try setting the loop mode for the animation in the animation player to none.

you’re setting the state to idle in the uptilt function, but there doesn’t seem to be function that triggers on the state change. With a state machine you want some code to trigger on leaving the attack state and entering the idle, and that’s where you can make sure your idle animation is starting.

Reading inputs should also be part of the state machine, each state overrides the input reading function so your “idle” input function checks for attack inputs but your “attack” input function only has to check for cancel inputs or specific combo chains (if you have any)

generally for something like this the state machine should be helping prevent if / else nesting and making it easier to debug problems like this, so I’d look into improving that