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

Godot 4 2D平台跳跃问题:按住跳跃键角色持续跳跃

2D平台游戏跳跃机制问题(Godot 4)

我用Godot 4开发一款2D平台游戏,微调跳跃机制时遇到问题:按住跳跃键时角色会持续跳跃。需求是角色只有在松开跳跃键后才能再次跳跃,并且落地时重置跳跃缓冲。


gravity_component.gd 组件代码

# gravity_component.gd
@export var actor: Node2D
@export var jump_height : float = 75.0
@export var jump_time_to_peak : float = 0.5
@export var jump_time_to_descent : float = 0.35

@onready var jump_velocity : float = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
@onready var bounce_velocity : float = ((jump_height) / jump_time_to_peak) * -1.0
@onready var float_velocity : float = ((jump_height) / jump_time_to_peak) * -1.0
@onready var jump_gravity : float = ((-2.0 * jump_height) / (pow(jump_time_to_peak, 2))) * -1.0
@onready var fall_gravity : float = ((-2.0 * jump_height) / (pow(jump_time_to_descent, 2))) * -1.0

func input_jump():
    if Input.is_action_pressed("jump"):
        actor.velocity.y = getJumpVelocity()

func float_jump():
    if Input.is_action_just_released("jump") and actor.velocity.y < (getJumpVelocity() / 2):
        actor.velocity.y = getFloatingVelocity()

player.gd 主脚本代码

# player.gd
var jump_available = true
var jump_buffer = false

func _physics_process(delta):
    gravity_component.apply_gravity(delta)
    handle_animations()
    handle_movement(delta)
    handle_jump()


func handle_jump():
    # DONT MOVE_AND_SLIDE HERE NUB
    if is_on_floor():
        if jump_buffer:
            gravity_component.input_jump()
            jump_buffer = false
        else:
            jump_buffer = true
    elif not is_on_floor():
        gravity_component.float_jump()
        state = JUMP

func handle_animations():
    match state:
        # some other code here
        JUMP:
            animatedSprite.play("jump")
            animatedSprite.flip_h = DIRECTION == -1
        _: # default
            animatedSprite.play("idle")

已尝试的方案

  • 将Input.is_action_pressed("jump")替换为Input.is_action_just_pressed("jump"),但角色有时在地面上无法响应跳跃输入。
  • 尝试在松开跳跃键时重置跳跃缓冲,代码如下,但未成功:
func resetJumpBuffer():
    if jump_buffer && Input.is_action_just_released("jump"):
        jump_buffer = true

解决方案

1. 重构gravity_component.gd,分离输入与物理逻辑

让组件只负责提供物理计算值,输入判断交给主脚本,提升复用性:

# gravity_component.gd
@export var actor: Node2D
@export var jump_height : float = 75.0
@export var jump_time_to_peak : float = 0.5
@export var jump_time_to_descent : float = 0.35

@onready var jump_velocity : float = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
@onready var bounce_velocity : float = ((jump_height) / jump_time_to_peak) * -1.0
@onready var float_velocity : float = ((jump_height) / jump_time_to_peak) * -1.0
@onready var jump_gravity : float = ((-2.0 * jump_height) / (pow(jump_time_to_peak, 2))) * -1.0
@onready var fall_gravity : float = ((-2.0 * jump_height) / (pow(jump_time_to_descent, 2))) * -1.0

# 直接返回跳跃速度,不再处理输入
func get_jump_velocity():
    return jump_velocity

func get_floating_velocity():
    return float_velocity

func apply_float_jump():
    actor.velocity.y = get_floating_velocity()

2. 完善player.gd的跳跃状态管理

添加跳跃键状态追踪,严格控制跳跃触发条件:

# player.gd
var jump_available = true
var jump_buffer = false
var jump_held = false  # 追踪跳跃键是否被按住

func _physics_process(delta):
    gravity_component.apply_gravity(delta)
    handle_animations()
    handle_movement(delta)
    handle_jump_input()  # 单独处理输入事件
    handle_jump()

# 分离输入处理,避免与跳跃逻辑混淆
func handle_jump_input():
    if Input.is_action_just_pressed("jump"):
        jump_held = true
        # 按下键时标记缓冲(无论是否在地面)
        jump_buffer = true
    if Input.is_action_just_released("jump"):
        jump_held = false
        jump_available = true  # 松开键后允许再次跳跃

func handle_jump():
    if is_on_floor():
        # 落地时重置跳跃缓冲
        jump_buffer = false
        # 满足条件时触发跳跃
        if jump_held and jump_available:
            actor.velocity.y = gravity_component.get_jump_velocity()
            jump_available = false  # 跳跃后锁定,直到松开键
            state = JUMP
    else:
        # 空中松开跳跃键触发漂浮
        if Input.is_action_just_released("jump") and actor.velocity.y < (gravity_component.get_jump_velocity() / 2):
            gravity_component.apply_float_jump()
        state = JUMP

func handle_animations():
    match state:
        # 保留原有动画逻辑
        JUMP:
            animatedSprite.play("jump")
            animatedSprite.flip_h = DIRECTION == -1
        _:
            animatedSprite.play("idle")

关键修改说明

  • 分离职责:组件专注物理计算,主脚本管理输入和状态,逻辑更清晰。
  • 跳跃锁定机制:用jump_available变量确保只有松开跳跃键后,才能触发下一次跳跃。
  • 落地重置缓冲:落地时直接清空jump_buffer,保证每次落地后可重新触发跳跃缓冲。
  • 输入追踪:用jump_held记录按键状态,避免重复触发跳跃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:53:14