Enemy looping animation instead of dying

Hello, I have an enemy that is supposed to play an animation that alters its skew, then queue_free(). It is not doing that, though. It does the animation forever after dying. I don’t know why this is happening.

My code:

extends CharacterBody2D

@onready var death_timer = $death_timer
@onready var anim_player = $AnimationPlayer
@onready var collison_shape = $CollisionShape2D

var player = null

var health = 5

func _process(delta: float) -> void:
	if player:
		look_at(player.global_position)
	else:
		print('no player')

	if health <= 0:
		anim_player.play("death_anim_one")
		collison_shape.disabled = true
	print(death_timer.time_left)

func _on_tree_entered() -> void: # 
	if owner:
		if owner.name == "main_one":
			var player = owner.player

func _on_death_timer_timeout() -> void:
	free()


It doesn’t look like you ever start the death timer.. so it never times out…

It’s happening because you’re calling the animation to start again each frame when health is zero. Your queue_free() isn’t working because you never start the death timer, and you’re calling the wrong function. Do this:

extends CharacterBody2D

@onready var death_timer = $death_timer
@onready var anim_player = $AnimationPlayer
@onready var collison_shape = $CollisionShape2D

var player = null

var health = 5:
	set(value):
		health = value
		if health <= 0:
			anim_player.play("death_anim_one")
			collison_shape.disabled = true
			death_timer.start()
		

func _process(delta: float) -> void:
	if player:
		look_at(player.global_position)
	else:
		print('no player')


func _on_tree_entered() -> void: # 
	if owner:
		if owner.name == "main_one":
			var player = owner.player


func _on_death_timer_timeout() -> void:
	queue_free()

Alternately, you can get rid of the death timer altogether:

extends CharacterBody2D

@onready var anim_player = $AnimationPlayer
@onready var collison_shape = $CollisionShape2D

var player = null

var health = 5:
	set(value):
		health = value
		if health <= 0:
			anim_player.play("death_anim_one")
			collison_shape.disabled = true
			anim_player.animation_finished.connect(_on_animation_finished)


func _process(delta: float) -> void:
	if player:
		look_at(player.global_position)
	else:
		print('no player')


func _on_tree_entered() -> void: # 
	if owner:
		if owner.name == "main_one":
			var player = owner.player


func _on_animation_finished(_animation_name: StringName) -> void:
	queue_free()

Could you explain the first part with the health variable? I wasn’t aware they could be used as functions and what does set(value) do?

variables cannot be used as functions. Every variable has a setter and a getter. These are created automatically. So in the above script, there is a set_health() and get_health() function under the hood. So:

health = 5
#Is that same as 
set_health(5)

#And

print(health)
#Is that same as 
print(get_health())

You can override those two functions, which is what I did. Following the link will give you details on it.

Thanks.

1 Like