Godot取消循环标记后敌人死亡动画仍循环,求问题排查
Godot 3D敌人死亡动画循环问题修复
你的核心问题是death()函数每帧都被调用,重复执行sprite.play("die")——哪怕动画本身没开循环,每帧强制从头播放也会让它看起来一直在循环。另外直接把动画调用放kill()里无效,是因为kill后状态没立刻切换到DEATH,后续follow()里的sprite.play("run")会覆盖死亡动画的播放请求。
修复步骤:
修改death()函数,避免重复触发动画播放
加个标记变量,确保死亡动画只在进入DEATH状态时播放一次:var death_animation_played = false # 新增标记变量 func death(): print("died") if not death_animation_played and not sprite.is_playing("die"): sprite.play("die") death_animation_played = true # 可选:动画播放完毕后销毁敌人 # if sprite.animation == "die" and not sprite.is_playing(): # queue_free()优化kill()函数,立即切换到DEATH状态
直接在kill里切换状态,避免依赖follow()里的判断延迟:func kill(): dead = true $CollisionShape3D.disabled = true change_state(States.DEATH) # 新增这一行额外检查动画资源设置
确认AnimatedSprite3D的"die"动画资源:- 取消
Loop选项 - 确认动画的结束帧设置正确,没有意外的循环逻辑
- 取消
修改后的完整代码(关键部分已标注):
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 var death_animation_played = 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() func death(): print("died") if not death_animation_played and not sprite.is_playing("die"): sprite.play("die") death_animation_played = true # 可选:动画播放完毕后销毁敌人 if sprite.animation == "die" and not sprite.is_playing(): queue_free() 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 change_state(States.DEATH) # 新增:立即切换到死亡状态 func _on_playerdetection_body_entered(body): player_entered = true
内容的提问来源于stack exchange,提问作者Space Kim
相关产品推荐
相关产品推荐

