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
相关产品推荐
相关产品推荐

