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

如何在使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:21:03