Godot平台游戏敌人跟随玩家功能实现求助
Godot 2D敌人跟随玩家功能实现优化方案
针对你当前的代码,核心问题是Follow状态未正确衔接动画与跟随逻辑,且跟随函数的实现和现有运动系统脱节。下面是具体的修正方案和优化后的代码:
核心问题梳理
- 当前
States.Follow分支仅播放attention动画,未调用follow_player函数 - attention动画结束后没有触发跟随逻辑的衔接
follow_player新建了velocity变量,和全局的motion变量冲突,导致重力和移动逻辑不一致- 跟随玩家时未处理敌人的转向(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
相关产品推荐
相关产品推荐

