You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现Godot角色平滑跳跃?解决角色瞬移升空后缓慢下落问题

嘿,我来帮你搞定这个角色瞬移+下落诡异的问题!先拆解下你当前代码里的核心问题:

  1. 两次调用move_and_slide:第一次你用direction * 100直接推角色,这相当于瞬间给了一个超大速度,直接把角色“甩”到空中;第二次又用speed再推一次,完全打乱了正常的移动逻辑。
  2. 重力处理错误:你直接给direction减去transform.basis.y(也就是向下的方向),这不是真实的重力——重力应该是持续的加速度,而不是瞬间改变方向。
  3. 跳跃逻辑混在方向里:把跳跃的向上方向和移动方向混在一起计算,导致速度叠加混乱,出现瞬移。

下面是优化后的代码,完全解决这些问题,实现平滑的移动和跳跃:

# 先在脚本顶部定义可调整的参数,方便你根据游戏需求微调
@export var move_speed: float = 5.0  # 地面移动速度
@export var gravity: float = 12.0    # 重力加速度
@export var jump_force: float = 5.0  # 跳跃初始速度

var velocity: Vector3 = Vector3.ZERO  # 用单独变量管理速度,保留帧间状态

func _physics_process(delta: float) -> void:
    # 1. 处理重力:只有不在地面时,持续叠加重力加速度
    if not is_on_floor():
        velocity.y -= gravity * delta

    # 2. 处理前后移动输入
    var input_dir: Vector3 = Vector3.ZERO
    if Input.is_action_pressed("mf"):
        input_dir -= transform.basis.z  # 向前
    elif Input.is_action_pressed("b"):
        input_dir += transform.basis.z  # 向后
    
    # 归一化输入方向,避免斜向移动(如果后续加左右键)速度过快
    if input_dir.length() > 0.01:
        input_dir = input_dir.normalized()
        # 设置水平方向的速度
        velocity.x = input_dir.x * move_speed
        velocity.z = input_dir.z * move_speed
    else:
        # 没有输入时重置水平速度,防止角色一直滑动
        velocity.x = 0.0
        velocity.z = 0.0

    # 3. 处理跳跃:只有在地面时才能触发跳跃,直接给向上的初始速度
    if Input.is_action_pressed("JUMP") and is_on_floor():
        velocity.y = jump_force

    # 4. 只调用一次move_and_slide,它会自动处理碰撞、地面检测,并返回更新后的速度
    velocity = move_and_slide(velocity, Vector3.UP)

关键优化点解释:

  • velocity变量管理速度:这样能保留上一帧的速度状态,比如重力会持续让角色下落速度越来越快,而不是瞬间改变方向。
  • 重力采用加速度方式:每帧叠加gravity * delta,让下落过程是平滑的加速,符合真实物理逻辑。
  • 跳跃直接设置y轴速度:给一个瞬间的向上初始速度,这样跳跃的手感会很自然,不会出现瞬移。
  • 单次调用move_and_slide:这个函数内部已经处理了碰撞修正、地面检测等逻辑,多次调用会导致速度叠加异常。
  • 输入归一化:避免斜向移动时速度翻倍,同时无输入时重置水平速度,防止角色“滑溜溜”停不下来。

你可以根据自己的游戏风格调整顶部的参数数值,比如增大jump_force让跳得更高,减小gravity让下落更慢。另外要确保你的角色有正确的碰撞体(比如CapsuleShape3D),这样is_on_floor()才能准确检测到地面。

内容的提问来源于stack exchange,提问作者Rares Cosma

火山引擎 最新活动