如何在使用move_and_slide_with_snap时实现上下斜坡移动速度一致
问题原因
move_and_slide_with_snap的吸附机制仅负责将角色固定在地面避免弹跳,不会修改引擎默认的速度投影逻辑:你传入的XZ平面速度会被自动投影到斜坡的切平面上,上坡时切向分量小于原水平速度所以移动变慢,下坡时切向分量大于原水平速度所以移动变快,这就是速率异常的核心原因。
修复方案
- 地面移动时将水平移动方向转换为沿斜坡表面的切向方向,确保实际移动速率始终等于设定的
player_speed,不受坡度影响。 - 保留原有snap逻辑,仅调整速度赋值逻辑即可。
修正后代码
# Jumping & Gravity var snap = Vector3() if is_on_floor() or (is_on_floor() and is_on_wall()): snap = -get_floor_normal() gravity_vec = Vector3.ZERO if Input.is_action_just_pressed("jump"): snap = Vector3.ZERO gravity_vec = Vector3.UP * jump_power elif not is_on_floor(): player_state = "In Air" snap = Vector3.ZERO gravity_vec += Vector3.DOWN * gravity * delta if is_on_ceiling(): gravity_vec = Vector3.DOWN * gravity * delta # Acceleration & Air Movement direction = direction.normalized() var current_acceleration: float if is_on_floor() and direction.dot(h_velocity) > 0: current_acceleration = acceleration else: current_acceleration = deacceleration if not is_on_floor(): current_acceleration *= air_control h_velocity = h_velocity.linear_interpolate(direction * player_speed, current_acceleration * delta) # 地面速度适配斜坡逻辑 if is_on_floor(): var floor_normal = get_floor_normal() # 将水平速度投影到斜坡切平面,保持速率不变 var slope_tangent = h_velocity.slide(floor_normal).normalized() velocity = slope_tangent * h_velocity.length() + gravity_vec else: velocity.x = h_velocity.x + gravity_vec.x velocity.z = h_velocity.z + gravity_vec.z velocity.y = gravity_vec.y velocity = move_and_slide_with_snap(velocity, snap, Vector3.UP, true, 4, max_slope_angle)
效果说明
用到的slide()是Godot内置的向量计算方法,会返回目标向量沿指定法向平面的切向分量,切向速度长度和原有水平速度长度完全一致,最终实现不同坡度下移动速率和平地完全相同。
内容的提问来源于stack exchange,提问作者Koto
相关产品推荐
相关产品推荐

