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

Godot 4中如何提升move_and_slide()像素级精准跳跃精度?

Godot 4中move_and_slide()跳跃精度问题解决方法

问题描述

在Godot 4中使用move_and_slide()实现2D平台跳跃时,无法达到预期的精准跳跃高度。参照GDC讲座参数编写的代码如下,预期跳跃高度为100像素,但实际达到112像素:

extends CharacterBody2D

# Parameters to fix
var JUMP_HEIGHT : float = 100.0;   # In pixels
var JUMP_WIDTH : float = 64.0;    # In pixels
var MAX_SPEED : float = 500.0;
# Deduced parameters from GDC talk
var jump_speed : float = 2 * JUMP_HEIGHT * MAX_SPEED / JUMP_WIDTH;
var gravity : float = 2 * JUMP_HEIGHT * pow(MAX_SPEED, 2) / pow(JUMP_WIDTH,2);


func _physics_process(delta):
    
    # Add gravity
    velocity.y += gravity * delta
    
    # Jump
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed;
    
    # Move
    move_and_slide()

观察发现:将时间缩放调至0.1,或增大JUMP_WIDTH放慢跳跃速度时,能达到预期的100像素高度,推测问题源于跳跃速度过快导致move_and_slide()的离散模拟精度不足。

解决方法(不放慢跳跃速度的前提下提升精度)

1. 子步模拟(Substep Simulation)

将单帧的物理计算拆分为多个更小的子步,减小每步的位移步长,让离散模拟更接近连续物理的计算结果:

extends CharacterBody2D

# Parameters to fix
var JUMP_HEIGHT : float = 100.0;   # In pixels
var JUMP_WIDTH : float = 64.0;    # In pixels
var MAX_SPEED : float = 500.0;
# Deduced parameters from GDC talk
var jump_speed : float = 2 * JUMP_HEIGHT * MAX_SPEED / JUMP_WIDTH;
var gravity : float = 2 * JUMP_HEIGHT * pow(MAX_SPEED, 2) / pow(JUMP_WIDTH,2);
# 子步数量,建议2-4,数值越高精度越好但性能消耗略增
const SUBSTEPS = 3

func _physics_process(delta):
    var sub_delta = delta / SUBSTEPS
    var did_jump = Input.is_action_just_pressed("jump") and is_on_floor()
    
    for _ in range(SUBSTEPS):
        # 重力累加
        velocity.y += gravity * sub_delta
        # 仅在第一个子步处理跳跃,避免重复触发
        if _ == 0 and did_jump:
            velocity.y = -jump_speed
        # 执行移动
        move_and_slide()

2. 顶点位置强制修正

检测跳跃到达顶点的瞬间,直接将角色位置修正到预期高度,完全消除离散误差:

extends CharacterBody2D

# Parameters to fix
var JUMP_HEIGHT : float = 100.0;   # In pixels
var JUMP_WIDTH : float = 64.0;    # In pixels
var MAX_SPEED : float = 500.0;
# Deduced parameters from GDC talk
var jump_speed : float = 2 * JUMP_HEIGHT * MAX_SPEED / JUMP_WIDTH;
var gravity : float = 2 * JUMP_HEIGHT * pow(MAX_SPEED, 2) / pow(JUMP_WIDTH,2);
var jump_start_y : float = 0.0

func _physics_process(delta):
    var prev_velocity_y = velocity.y
    
    # 重力累加
    velocity.y += gravity * delta
    
    # 跳跃触发,记录起跳位置
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed
        jump_start_y = position.y
    
    move_and_slide()
    
    # 检测跳跃顶点(速度从向上变为向下/静止)
    if prev_velocity_y < 0 and velocity.y >= 0:
        # 强制修正到预期高度
        position.y = jump_start_y - JUMP_HEIGHT
        velocity.y = 0

3. 适配离散帧的参数计算

原GDC公式基于连续物理模型,在离散帧下可改用经典跳跃公式调整参数,让计算更适配Godot的物理模拟:

# 先固定JUMP_HEIGHT和gravity,计算精准的jump_speed
var JUMP_HEIGHT : float = 100.0
var gravity : float = 2000.0 # 可根据需要调整
var jump_speed : float = sqrt(2 * gravity * JUMP_HEIGHT)

# 再根据JUMP_WIDTH调整gravity,让跳跃时长匹配预期
var jump_duration = JUMP_WIDTH / MAX_SPEED
gravity = 2 * JUMP_HEIGHT / (jump_duration * jump_duration)

这种方式的参数计算更贴合离散物理的实际运行逻辑,能减少精度偏差。


内容的提问来源于stack exchange,提问作者GD Clone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:35:34