You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot取消循环标记后敌人死亡动画仍循环,求问题排查

Godot 3D敌人死亡动画循环问题修复

你的核心问题是death()函数每帧都被调用,重复执行sprite.play("die")——哪怕动画本身没开循环,每帧强制从头播放也会让它看起来一直在循环。另外直接把动画调用放kill()里无效,是因为kill后状态没立刻切换到DEATH,后续follow()里的sprite.play("run")会覆盖死亡动画的播放请求。

修复步骤:

  1. 修改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()
    
  2. 优化kill()函数,立即切换到DEATH状态
    直接在kill里切换状态,避免依赖follow()里的判断延迟:

    func kill():
        dead = true
        $CollisionShape3D.disabled = true
        change_state(States.DEATH)  # 新增这一行
    
  3. 额外检查动画资源设置
    确认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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:07:10