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

Unity可变跳跃高度实现异常:随机跳至更高高度问题排查

解决可变跳跃高度的异常弹射问题

问题根源

你的代码核心问题是输入事件与物理更新的时机不匹配:

  • Input.GetKeyUp 是帧驱动的输入事件,必须在 Update 中处理。FixedUpdate 是固定时间步长的物理更新,执行频率和游戏帧频不同步,快速按键时,GetKeyUp 事件可能被遗漏或在错误的物理帧触发,导致速度修改逻辑失效或异常。
  • 跳跃触发时未立即禁用 onGround,可能导致极端情况下多次触发跳跃力叠加。

修复后的代码

Rigidbody2D rb;
[SerializeField] float force;
[SerializeField] bool onGround;

// 标记是否需要在物理帧中修改跳跃速度
bool shouldCutJump;

void Start()
{
    rb = GetComponent<Rigidbody2D>();
}

void Update()
{
    // 跳跃输入在Update中处理
    if (Input.GetKeyDown(KeyCode.Space) && onGround)
    {
        onGround = false;
        rb.AddForce(Vector2.up * force, ForceMode2D.Impulse);
    }

    // 跳跃中断输入也在Update中捕获
    if (Input.GetKeyUp(KeyCode.Space) && rb.velocity.y > 0)
    {
        shouldCutJump = true;
    }
}

private void FixedUpdate() 
{
    // 物理帧中统一处理速度修改
    if (shouldCutJump)
    {
        rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
        shouldCutJump = false;
    }
}

private void OnCollisionEnter2D(Collision2D other) 
{
    if (other.gameObject.CompareTag("Ground"))
        onGround = true;
}

private void OnCollisionExit2D(Collision2D other) 
{
    if (other.gameObject.CompareTag("Ground"))
        onGround = false;   
}

关键改动说明

  1. 输入逻辑全部移至Update:
    跳跃触发和跳跃中断的输入事件都在Update中处理,确保不会遗漏任何输入帧。
  2. 用标志位传递物理修改指令:
    用shouldCutJump标记需要在物理帧中修改速度,避免输入事件和物理更新的时机冲突。
  3. 立即禁用地面标记:
    触发跳跃时立刻将onGround设为false,彻底避免多次跳跃触发的可能。

额外优化建议

如果希望更精准的跳跃高度控制,可以改用直接设置速度代替AddForce,避免物理引擎的力叠加波动:

// 替换AddForce的代码
rb.velocity = new Vector2(rb.velocity.x, Mathf.Sqrt(2 * force * Physics2D.gravity.magnitude));

这里的force可以视为跳跃的最大高度对应的速度参数,公式来自自由落体的速度-高度关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:48:14