Death animation of enemy is keep looping even though I unchecked the looping mark. Does my code has problem or is it just a error in godot?
I keep checked looping mark and change the code in different way but the result was same. But if I erase DEATH state and put animation in kill fuction animation does not work.
This is my code:
extends CharacterBody3D
@export var attack_range = 2.0
@onready var move_speed = 6
@onready var player_entered = false
@onready var player: CharacterBody3D = get_tree().get_first_node_in_group("player")
@onready var sprite = $AnimatedSprite3D
var dead = false
enum States {IDLE, FOLLOW, DEATH}
var state = States.IDLE
func _physics_process(delta):
match state:
States.IDLE:
idle()
States.FOLLOW:
follow()
States.DEATH:
death()
func change_state(newState):
state = newState
func idle():
print("idle")
sprite.play()
if player_entered:
change_state(States.FOLLOW)
func follow():
print("follow")
sprite.play("run")
var dir = player.global_position - global_position
dir.y = 0.0
dir = dir.normalized()
velocity = dir * move_speed
move_and_slide()
attempt_to_kill_player()
if dead:
change_state(States.DEATH)
func death():
print("died")
sprite.play("die")
func attempt_to_kill_player():
var dist_to_player = global_position.distance_to(player.global_position)
if dist_to_player > attack_range:
return
var eye_line = Vector3.UP * 1.5
var query = PhysicsRayQueryParameters3D.create(global_position+eye_line, player.global_position+eye_line, 1)
var result = get_world_3d().direct_space_state.intersect_ray(query)
if result.is_empty():
player.kill()
func kill():
dead = true
$CollisionShape3D.disabled = true
func _on_playerdetection_body_entered(body):
player_entered = true
_physics_process is still called every physics frame. So if your in the death state. The death function is called every frame. The sprite.play("die") call will play the animation again, when a animation finished, so you have to change the code there.
One possible change could be, to create a flag, which is set to true after the animation played once. This can be done in the animation finished signal handler.
var death_animation_played = false
func _on_animated_sprite_2d_animation_finished():
if sprite.animation == "die":
death_animation_played = true
func death():
print("died")
if death_animation_played == false:
sprite.play("die")
Connect the function _on_animated_sprite_2d_animation_finished
to the animation_finished signal of you AnimatedSprite2D.
Edit: Just got an idea, which is even easier. Check which animation is/was playing last and only then play the die animation, if it wasnt the last one:
func death():
print("died")
if not sprite.animation == "die":
sprite.play("die")