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

Godot平台游戏敌人跟随玩家功能实现求助

Godot 2D敌人跟随玩家功能实现优化方案

针对你当前的代码,核心问题是Follow状态未正确衔接动画与跟随逻辑,且跟随函数的实现和现有运动系统脱节。下面是具体的修正方案和优化后的代码:

核心问题梳理

  1. 当前States.Follow分支仅播放attention动画,未调用follow_player函数
  2. attention动画结束后没有触发跟随逻辑的衔接
  3. follow_player新建了velocity变量,和全局的motion变量冲突,导致重力和移动逻辑不一致
  4. 跟随玩家时未处理敌人的转向(scale和dir变量)

修正步骤与代码实现

1. 衔接动画与跟随逻辑

监听attention动画的结束信号,在动画播放完毕后才开始跟随玩家。可以通过代码连接动画结束信号,或者直接在状态中判断处理:

2. 优化Follow状态与跟随函数

修改_physics_process中的Follow分支逻辑,同时重构follow_player函数,复用全局motion变量,保持和现有运动系统一致:

extends KinematicBody2D

var speed = 50
var motion = Vector2()
var gravity = 30
var dir = 1
var state_machine
var can_move = true
var current_state = States.RUN
onready var player = get_node("/root/exp/Boxer King")
# 新增:标记attention动画是否播放完毕
var attention_finished = false

enum States {
    RUN,
    Attack,
    Follow,
    Attention
}

# Reference to Timer node
onready var timer = $Timer
onready var RayFloor = $RayFloor
onready var RayWall = $RayWall
onready var animation_tree = $AnimationTree


func _ready():
    # 连接attention动画的finished信号
    animation_tree.connect("animation_finished", self, "_on_animation_finished")
    state_machine = animation_tree.get("parameters/playback")


func _physics_process(delta):
    # gravity 
    motion.y += gravity
    
    match current_state:
        States.RUN:
            attention_finished = false
            handle_movement()
        States.Attack:
            state_machine.travel("attack")
            motion.x = 0
            timer.paused = true  # 原代码漏了赋值操作
        States.Follow:
            timer.paused = true
            if not attention_finished:
                # 先播放attention动画
                state_machine.travel("attention")
            else:
                # 动画结束后执行跟随
                follow_player()
                state_machine.travel("run")  # 跟随状态播放run动画


func handle_movement():
    # Floor check
    if RayFloor.is_colliding():
        if dir >= 1:
            motion.x = speed
            state_machine.travel("run")
        else:
            motion.x = -speed
            state_machine.travel("run")
        # Reset the timer when the floor is colliding
        timer.wait_time = rand_range(2.0, 4.0)
        timer.start()
    else:
        # If the floor is not colliding, stop movement
        motion.x = 0
        state_machine.travel("idle")

    # Wall check
    if RayWall.is_colliding():
        dir = -dir
        scale.x *= dir
    
    motion = move_and_slide(motion, Vector2.UP)


func _on_Timer_timeout():
    dir = -dir
    scale.x *= -1
    timer.wait_time = rand_range(1.0, 3.0)


func _on_check_box_body_entered(body):
    if body.is_in_group("player"):
        attention_finished = false
        current_state = States.Follow


func _on_check_box_body_exited(body):
    if body.is_in_group("player"):
        current_state = States.RUN
        timer.paused = false
    

func follow_player():
    if not player:
        return
    
    # 计算朝向玩家的方向
    var direction = (player.global_position - global_position).normalized()
    
    # 处理敌人转向
    if direction.x > 0 and dir != 1:
        dir = 1
        scale.x = abs(scale.x)
    elif direction.x < 0 and dir != -1:
        dir = -1
        scale.x = -abs(scale.x)
    
    # 设置X轴移动速度,保持Y轴重力不受影响
    motion.x = direction.x * speed
    
    # 执行移动(复用现有move_and_slide逻辑)
    motion = move_and_slide(motion, Vector2.UP)


func _on_animation_finished(animation_name):
    # 当attention动画播放完毕时标记状态
    if animation_name == "attention":
        attention_finished = true

关键优化点说明

  • 动画衔接:通过animation_finished信号监听attention动画结束,确保跟随逻辑在动画播放完后才触发
  • 运动逻辑统一:复用全局motion变量,避免新建velocity导致重力和移动逻辑冲突
  • 转向处理:根据玩家位置自动调整敌人的dir和scale,保证朝向正确
  • 状态重置:在玩家离开检测区域时重置attention_finished标记,避免再次进入Follow状态时直接跳过动画

内容的提问来源于stack exchange,提问作者5odha Minni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:17:41