How to stop animations in animation tree

Godot Version
godot 4

Question
I’m trying my hand at a animation tree state machine but I’ve made a mistake somewhere along the line and I now have an issue. If the enemy dies while it’s in the attack animation it doesn’t play the death animation, but just disappears instead. This seems to be due to the “await animation finished” lines:

	while animation_tree["parameters/conditions/is_attacking"] == true:
		velocity.x = 0
		await animation_tree.animation_finished


func _on_start_attack_area_body_entered(body):
	if body.is_in_group("Player_body"):
		is_attacking = true
		animation_tree["parameters/conditions/is_attacking"] = true
		await animation_tree.animation_finished
		animation_tree["parameters/conditions/is_attacking"] = false

But when I try to remove them the entire code stops working

Any and all help is greatly appreciated

Code for skeleton enemy:

#things to do:
#1
	#Skeleton dead animation should interrupt attack animation
	#currently it dosent and skeleton disappears after attack animation is finished
#2
	#if player enters "start area attack shape" in the last frames when enemy isn't 
	#damaging the player, the skeleton won't attack again and will keep walking forward


extends CharacterBody2D

#-------------------------------------------
const speed = 50
#-------------------------------------------
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var chase = false
var is_attacking = false
#-------------------------------------------
@onready var player = get_node("../../Player/Player")
@onready var skeleton = $"."
@onready var animation_tree: AnimationTree = $AnimationTree
@onready var health = $Damageable_skeleton.Skeleton_health


func _on_ready():
	add_to_group("enemy")
	animation_tree.active = true

#func process differs from physics_process so as to maintain overview
func _process(_delta):
	update_animation_parameters()
	if is_attacking == false:
		$Attack_detection.monitoring = false
#adds skeleton to enemy group - only works this way for some reason
	if $".".is_in_group("enemy") != true:
		add_to_group("enemy")
	print(animation_tree["parameters/conditions/is_attacking"])

#skeleton physics and movement
func _physics_process(delta):
	if not is_on_floor():
		velocity.y += gravity * delta
	move_and_slide()
	var direction = (player.position - self.global_position).normalized()
	if chase == true:
		velocity.x = direction.x * speed
	if direction.x < 0:
		get_node("AnimatedSprite2D").flip_h = true
		$Attack_detection.scale.x = -1
		$Start_attack_area.scale.x = -1
	else:
		get_node("AnimatedSprite2D").flip_h = false
		$Attack_detection.scale.x = 1
		$Start_attack_area.scale.x = 1


#-------------------------------------------
# if player is in range skeleton will chase the player
func _on_detection_area_body_entered(body):
	if body.is_in_group("Player_body"):
		chase = true

func _on_detection_area_body_exited(body):
	if body.is_in_group("Player_body"):
		chase = false
		velocity.x = 0

#animation tree state machine code
func update_animation_parameters():
#movement animation
	if(velocity.x == 0):
		animation_tree["parameters/conditions/Idle"] = true
		animation_tree["parameters/conditions/is_moving"] = false
	elif(velocity.x != 0):
		animation_tree["parameters/conditions/Idle"] = false
		animation_tree["parameters/conditions/is_moving"] = true
#death animation
	if $Damageable_skeleton.Skeleton_health == 0:
		#figure out how to cancel all other animations before playing dead animation
		animation_tree["parameters/conditions/Dead"] = true
	if is_attacking == true and $Attack_detection.monitoring == true:
		Game.playerHP -= 3

#big issue in code below
	while animation_tree["parameters/conditions/is_attacking"] == true:
		velocity.x = 0
		await animation_tree.animation_finished

#attack animations
func _on_start_attack_area_body_entered(body):
	if body.is_in_group("Player_body"):
		is_attacking = true
		animation_tree["parameters/conditions/is_attacking"] = true
		await animation_tree.animation_finished
		animation_tree["parameters/conditions/is_attacking"] = false



func _on_start_attack_area_body_exited(_body):
	is_attacking = false

Animation tree setup:

Taking damage and death logic for the enemy is in another “taking damage script”

Hi. Sorry for having no time to test your code.

Just in my view, the animation do not work because you toggle the is_attack codition immediately after removing the line await…. Additionally, the is_attack codition don’t be canceled while your monster die. So the while loop (at issue you annotated) will not be stoped.

Try to modify:

	if $Damageable_skeleton.Skeleton_health == 0:
		#figure out how to cancel all other animations before playing dead animation
		animation_tree["parameters/conditions/Dead"] = true
	    is_attacking = false
        animation_tree.travel("death")
        

Please notify that the attack animation may play once after entering the death condition, due to the await in your context.

Hopefully my reply can help you. You can paste the new version code whatever the problem has been solved.

Sorry for late reply - it dosen’t seem to work, since I am using the built in state machine in the animation tree. I get the error "Invalid call. nonexistent function in ‘animation tree’ "

I have since changed my code for attacking, so as to circumvent the “is attacking” immediately changing from true to false, to this:

	if is_attacking == true and $Attack_detection.monitoring == true:
		Game.playerHP -= 3
	while animation_tree["parameters/conditions/is_attacking"] == true:
		velocity.x = 0
#if skeleton isn't dead finish animation then set condition to false
		if animation_tree["parameters/conditions/Dead"] != true:
			await animation_tree.animation_finished
			animation_tree["parameters/conditions/is_attacking"] = false
1 Like