2D史莱姆敌人跳跃异常:首次正常后续反向跳转问题求助
史莱姆2D敌方单位跳跃方向异常问题排查与修复
问题描述
- 首次跳跃符合预期,朝向玩家方向;
- 后续跳跃会莫名朝向与玩家位置相反的方向。

跳跃代码片段
if is_on_floor(): var player_pos = get_node("../Player").get_global_position() var self_pos = get_global_position() var jump_distance = (player_pos - self_pos).normalized() var distance_to_player = player_pos.distance_to(self_pos) var horizontal_speed = min_speed + (distance_to_player / max_distance) * (max_speed - min_speed) horizontal_speed = min(max_speed, max(min_speed, horizontal_speed)) velocity = jump_distance velocity.x *= horizontal_speed * direction velocity.y = -jumpmove_height #-jump_height velocity = move_and_slide(velocity, Vector2.UP) $Position2D/SlimeSkin/AnimationPlayer.play("SlimePrototype Attack") $Jump_Cooldown.start() print("Do Jump")
完整代码
extends KinematicBody2D var speed = 20 var min_speed = 0 #min_speed for jump horizontal speed var max_speed = 250 #max_speed for jump horizontal speed var max_distance = 300 #max distance for jump distance var direction = 1 export var jumpmove_height : float export var jump_time_to_peak : float export var jump_time_to_descent : float onready var jump_velocity : float = ((2.0 * jumpmove_height) / jump_time_to_peak) * -1.0 onready var jump_gravity : float = ((-2.0 * jumpmove_height) / (jump_time_to_peak * jump_time_to_peak)) * -1.0 onready var fall_gravity : float = ((-2.0 * jumpmove_height) / (jump_time_to_descent * jump_time_to_descent)) * -1.0 var velocity = Vector2.ZERO var is_idle = true func _ready(): is_idle = true $Idle_Timer.start() pass func get_gravity() -> float: return jump_gravity if velocity.y < 0.0 else fall_gravity func _physics_process(delta): if velocity.x>0: $Position2D.scale.x=1 elif velocity.x<0: $Position2D.scale.x=-1 if is_on_wall() or not $Position2D/FloorRay.is_colliding() and is_on_floor(): direction = direction * -1 velocity.y += get_gravity() * delta if is_on_floor(): velocity.x = 0 velocity = move_and_slide(velocity, Vector2.UP) if is_idle: velocity.x = speed * direction if is_on_wall() or not $Position2D/FloorRay.is_colliding() and is_on_floor(): direction = direction * -1 velocity = move_and_slide(velocity, Vector2.UP) $Position2D/SlimeSkin/AnimationPlayer.play("SlimePrototype Idle") func _on_Timer_timeout(): if is_on_floor(): var player_pos = get_node("../Player").get_global_position() var self_pos = get_global_position() var jump_distance = (player_pos - self_pos).normalized() var distance_to_player = player_pos.distance_to(self_pos) var horizontal_speed = min_speed + (distance_to_player / max_distance) * (max_speed - min_speed) horizontal_speed = min(max_speed, max(min_speed, horizontal_speed)) velocity = jump_distance velocity.x *= horizontal_speed * direction velocity.y = -jumpmove_height #-jump_height velocity = move_and_slide(velocity, Vector2.UP) $Position2D/SlimeSkin/AnimationPlayer.play("SlimePrototype Attack") $Jump_Cooldown.start() print("Do Jump") func _on_Idle_Timer_timeout(): is_idle = false $Timer.start() $Position2D/SlimeSkin/AnimationPlayer.play("SlimePrototype Charge") print("IDLE TIMER TIMEOUT") pass # Replace with function body. func _on_Jump_Cooldown_timeout(): yield(get_tree().create_timer(0.5), "timeout") is_idle = true pass # Replace with function body.
问题原因
核心问题是**direction变量的错误复用**:
direction原本是idle状态下史莱姆左右移动的转向标记,会在碰撞墙体或地板缺失时自动翻转;- 跳跃逻辑中,
jump_distance.x已经通过player_pos - self_pos计算出了朝向玩家的正确水平方向(正数为右,负数为左),但代码额外乘以了direction,导致首次跳跃后direction被翻转时,后续跳跃的水平方向被反向。
修复方案
直接修复方向计算
修改_on_Timer_timeout中的速度赋值代码,移除direction对水平速度的影响:
# 原代码 velocity.x *= horizontal_speed * direction # 修改为 velocity.x *= horizontal_speed
可选优化:统一朝向控制
为避免direction变量混淆,跳跃时直接根据玩家位置设置 sprite 缩放,替代依赖velocity.x的判断:
在跳跃逻辑中添加:
# 在velocity赋值后添加 if jump_distance.x > 0: $Position2D.scale.x = 1 else: $Position2D.scale.x = -1
这样可以确保跳跃时的朝向完全由玩家位置决定,不受idle状态下direction变化的干扰。
内容的提问来源于stack exchange,提问作者DeruDeru
相关产品推荐
相关产品推荐

