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

Godot街机角色三档地面状态跳跃及空中无输入运动实现问题

解决方案(Godot 3.x/4.x通用思路)

1. 修复跳跃时立即停下的问题:保留地面水平速度

你当前的核心问题是触发跳跃时重置了水平速度。要让角色带着地面速度起跳,只需在跳跃前记录当前水平速度,空中阶段保持该速度即可(符合“落地前保持运动状态”的需求)。

示例代码(以CharacterBody2D/KinematicBody2D为例):

# 定义核心变量
var is_on_floor: bool = false
var current_horizontal_velocity: float = 0.0
var jump_impulse: float = -400.0 # 向上为负方向,可根据你的游戏调整

func _physics_process(delta: float):
    is_on_floor = is_on_floor()

    if is_on_floor:
        # 地面运动逻辑(你的已有代码)
        handle_ground_movement(delta)
        # 记录当前地面水平速度,用于起跳时继承
        current_horizontal_velocity = velocity.x
    else:
        # 空中锁定水平输入,严格保持起跳前的速度
        velocity.x = current_horizontal_velocity

    # 仅在地面响应跳跃输入
    if is_on_floor and Input.is_action_just_pressed("jump"):
        velocity.y = jump_impulse
        # 不要在这里重置velocity.x!

2. 实现三种跳跃类型并区分地面速度

根据需求,三种跳跃的核心差异在于水平速度继承规则垂直冲量大小,以下提供两种实现方案:

方案A:绑定独立输入(适合明确的三档跳跃触发)

给直上、小弧度、大弧度跳跃分别绑定不同的输入键(如jump_up/jump_small/jump_big):

# 定义三种跳跃参数
var jump_up_impulse: float = -350.0
var jump_small_impulse: float = -400.0
var jump_big_impulse: float = -500.0
var walk_speed: float = 150.0
var run_speed: float = 300.0
var direction: float = 0.0

func _physics_process(delta: float):
    direction = Input.get_axis("move_left", "move_right")
    is_on_floor = is_on_floor()

    if is_on_floor:
        handle_ground_movement(delta)
        current_horizontal_velocity = velocity.x

        # 直上跳跃:清零水平速度,垂直冲量最小
        if Input.is_action_just_pressed("jump_up"):
            velocity.x = 0.0
            velocity.y = jump_up_impulse
            current_horizontal_velocity = 0.0
        # 小弧度跳跃:继承行走速度,垂直冲量中等
        elif Input.is_action_just_pressed("jump_small"):
            velocity.x = walk_speed * direction
            velocity.y = jump_small_impulse
            current_horizontal_velocity = velocity.x
        # 大弧度跳跃:继承奔跑速度,垂直冲量最大
        elif Input.is_action_just_pressed("jump_big"):
            velocity.x = run_speed * direction
            velocity.y = jump_big_impulse
            current_horizontal_velocity = velocity.x
    else:
        velocity.x = current_horizontal_velocity

方案B:长按充电区分(复古游戏常用逻辑)

通过按住跳跃键的时长触发不同跳跃类型,更符合复古游戏操作习惯:

var jump_charge_timer: float = 0.0
var is_charging_jump: bool = false
var is_running: bool = false # 需在地面运动逻辑中更新

func _physics_process(delta: float):
    is_on_floor = is_on_floor()

    if is_on_floor:
        handle_ground_movement(delta)
        current_horizontal_velocity = velocity.x

        # 跳跃充电逻辑
        if Input.is_action_pressed("jump"):
            is_charging_jump = true
            jump_charge_timer += delta
            jump_charge_timer = min(jump_charge_timer, 0.5) # 限制最大充电时长
        elif Input.is_action_just_released("jump") and is_charging_jump:
            is_charging_jump = false
            # 根据充电时长切换跳跃类型
            match true:
                jump_charge_timer < 0.1:
                    # 直上跳跃
                    velocity.x = 0.0
                    velocity.y = -350.0
                    current_horizontal_velocity = 0.0
                jump_charge_timer < 0.3:
                    # 小弧度跳跃:继承当前地面速度
                    velocity.y = -400.0
                    current_horizontal_velocity = velocity.x
                jump_charge_timer >= 0.3:
                    # 大弧度跳跃:强制使用奔跑速度+最大垂直冲量
                    velocity.x = run_speed * direction
                    velocity.y = -500.0
                    current_horizontal_velocity = velocity.x
            jump_charge_timer = 0.0
    else:
        velocity.x = current_horizontal_velocity

3. 行走转奔跑逻辑补全(细节优化)

针对“行走状态持续1秒后立即切换为奔跑”的需求,需注意仅在持续行走时计时,停下时重置计时器:

var walk_duration_timer: float = 0.0
var is_walking: bool = false

func handle_ground_movement(delta: float):
    direction = Input.get_axis("move_left", "move_right")
    if direction != 0:
        is_walking = true
        walk_duration_timer += delta
        # 行走满1秒切换奔跑
        if walk_duration_timer >= 1.0:
            is_running = true
            velocity.x = run_speed * direction
        else:
            is_running = false
            velocity.x = walk_speed * direction
    else:
        is_walking = false
        is_running = false
        walk_duration_timer = 0.0
        velocity.x = 0.0

关键注意事项

  • 所有运动逻辑必须放在_physics_process中,避免物理帧和渲染帧不同步导致的抖动。
  • 确保current_horizontal_velocity在每次落地时更新,保证每次跳跃都继承最新的地面速度状态。
  • Godot 4和3.x的核心逻辑一致,仅节点名称(如CharacterBody2D替代KinematicBody2D)和部分方法细节有差异,可根据版本微调。

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

火山引擎 最新活动