Godot 4.0 2D基础跳跃异常求助:仅按跳跃键角色飞至顶部外
Godot 4.0 2D跳跃异常问题解决
问题根源
你遇到的问题核心是速度归一化逻辑错误:
- 仅按跳跃键时,
velocity只有y轴分量(值为-JUMP_FORCE),执行velocity.normalized()后会变成Vector2(0, -1),再乘以move_speed会让y轴速度直接等于move_speed,远大于你设定的跳跃力,导致角色瞬间飞出去。 - 同时按移动键时,
velocity是x+y的向量,归一化后y轴分量被缩小,最终y轴速度不会异常放大,所以表现正常。
修正方案
把横向移动和跳跃的速度计算完全分开,不要对包含跳跃力的velocity做整体归一化,同时修正重力计算逻辑(原逻辑会导致重力加速度随时间递增,不符合常规物理效果):
- 横向移动直接设置固定速度,避免累加后归一化
- 跳跃的y轴速度保持独立,不参与归一化操作
- 重力改为每帧增加
GRAVITY * delta,保持恒定加速度 - 初始化未定义的
time_on_jump变量
修正后的代码
const GRAVITY = 1000.0 # 增大重力值适配delta时间,数值可根据手感调整 const JUMP_FORCE = 400.0 const MOVE_SPEED = 200.0 # 明确定义移动速度常量 var screen_size var velocity = Vector2.ZERO var is_on_floor = true var time_on_jump = 0.0 # 初始化变量 var init_pos = Vector2.ZERO # 统一初始位置变量 func _ready(): screen_size = get_viewport_rect().size init_pos = Vector2(init_pos_x, init_pos_y) position = init_pos func _process(delta): # 地面状态重置纵向速度 if is_on_floor: velocity.y = 0 time_on_jump = 0.0 # 横向移动处理 velocity.x = 0 if Input.is_action_pressed("move_right"): velocity.x = MOVE_SPEED if Input.is_action_pressed("move_left"): velocity.x = -MOVE_SPEED # 跳跃处理 if Input.is_action_just_pressed("jump") and is_on_floor: is_on_floor = false velocity.y = -JUMP_FORCE # 重力与落地检测 if not is_on_floor: velocity.y += GRAVITY * delta # 落地判定 if position.y >= init_pos.y: is_on_floor = true position.y = init_pos.y velocity.y = 0 # 动画处理 if velocity.x != 0: $AnimatedSprite2D.flip_h = velocity.x < 0 $AnimatedSprite2D.play("run") else: $AnimatedSprite2D.play("idle") # 更新位置 position += velocity * delta # 边界限制 position.x = clamp(position.x, 0, screen_size.x) position.y = clamp(position.y, 0, screen_size.y) print_debug("Position: ", position, " Velocity: ", velocity)
额外说明
- 调整了
GRAVITY和JUMP_FORCE的数值,因为原代码中用delta计算位置,需要更大的数值才能得到正常手感,你可以根据自己的需求微调。 - 统一了初始位置变量,避免重复定义。
- 移除了未实现的
start(pos)调用。
内容的提问来源于stack exchange,提问作者Alberto Sánchez
相关产品推荐
相关产品推荐

