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

Unity 3D双跳功能实现异常:Input.GetAxis相关问题排查

Unity双跳功能异常问题排查与修复

问题描述

普通跳跃功能正常,但二次跳跃存在异常:

  • 最初用Input.GetButtonUp("Jump")实现时,控制台显示已触发二次跳跃,但角色实际不执行,偶尔需要按空格键30次才能成功触发。
  • 改用jump = Input.GetAxisRaw("Jump")后,按下空格键会触发多次函数调用,导致地面检测状态变为false。

原脚本代码

public class PlayerBHV : MonoBehaviour
{
    private float horizontal;
    private float jump;
    public float speed = 1000f;
    public float jumpHeight = 50f;
    public float run = 1.5f;

    public Transform groundCheck;
    public float groundCheckRadius;
    public LayerMask WhatIsGround;
    public bool grounded;
    public bool doubleJump;

    [SerializeField] private Rigidbody2D rb;

    void Start()
    {

    }

    private bool IsGrounded()
    {
        return grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius ,WhatIsGround);
    }

    void Update()
    {
        IsGrounded();
        horizontal = Input.GetAxisRaw("Horizontal");
        jump = Input.GetAxisRaw("Jump");

        if (grounded && jump == 0)
        {
            doubleJump = false;
        }

        if (rb != null)
        {
            if (Input.GetKey(KeyCode.LeftShift))
            {
                rb.velocity = new Vector2(horizontal, 0) * Time.fixedDeltaTime * speed * run;
            }

            if (!Input.GetKey(KeyCode.LeftShift))
            {
                rb.velocity = new Vector2(horizontal, 0) * Time.fixedDeltaTime * speed;
            }

            if (jump != 0 && grounded)
            {
                rb.velocity = new Vector2(horizontal, jumpHeight);
                Debug.Log("skok");
            }

            if (jump != 0 && !doubleJump && !grounded)
            {
                    Debug.Log("tutaj");
                    rb.velocity = new Vector2(horizontal, jumpHeight);

                    doubleJump = true;
            }
        }
    }

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

问题分析

  1. 输入检测逻辑错误:Input.GetAxisRaw("Jump")在Update中会每帧检测,按住空格时会持续触发跳跃逻辑,导致双跳状态被反复修改,同时干扰地面检测。
  2. Rigidbody2D初始化时机错误:FixedUpdate中每次都执行rb = GetComponent<Rigidbody2D>(),属于冗余操作,且可能导致帧同步问题。
  3. 速度设置逻辑问题:
    • Update中使用Time.fixedDeltaTime错误,应该用Time.deltaTime;
    • 直接覆盖rb.velocity的Y轴值会忽略重力影响,导致跳跃手感异常;
    • 移动逻辑和跳跃逻辑混在Update中,物理操作应该放在FixedUpdate里。
  4. 双跳重置逻辑不严谨:仅当grounded && jump == 0时重置双跳,若落地时刚好按住空格,双跳无法重置。

修复后的代码

public class PlayerBHV : MonoBehaviour
{
    private float horizontal;
    public float speed = 1000f;
    public float jumpHeight = 50f;
    public float run = 1.5f;

    public Transform groundCheck;
    public float groundCheckRadius;
    public LayerMask WhatIsGround;
    public bool grounded;
    public bool doubleJump;

    [SerializeField] private Rigidbody2D rb;

    void Awake()
    {
        // 初始化Rigidbody2D,避免重复获取
        rb = GetComponent<Rigidbody2D>();
    }

    private bool IsGrounded()
    {
        return grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, WhatIsGround);
    }

    void Update()
    {
        IsGrounded();
        horizontal = Input.GetAxisRaw("Horizontal");

        // 落地直接重置双跳,无需判断输入状态
        if (grounded)
        {
            doubleJump = false;
        }

        // 只在按下跳跃键的瞬间触发一次
        if (Input.GetButtonDown("Jump"))
        {
            if (grounded)
            {
                Jump();
                Debug.Log("普通跳跃");
            }
            else if (!doubleJump)
            {
                Jump();
                doubleJump = true;
                Debug.Log("二次跳跃");
            }
        }
    }

    private void FixedUpdate()
    {
        // 移动逻辑放在FixedUpdate中,使用Time.fixedDeltaTime处理物理
        float moveSpeed = Input.GetKey(KeyCode.LeftShift) ? speed * run : speed;
        rb.velocity = new Vector2(horizontal * moveSpeed * Time.fixedDeltaTime, rb.velocity.y);
    }

    private void Jump()
    {
        // 保留X轴速度,只修改Y轴跳跃速度,避免覆盖移动状态
        rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
    }
}

关键修改点说明

  • 输入检测:改用Input.GetButtonDown("Jump"),确保每次按下空格只触发一次跳跃逻辑。
  • Rigidbody初始化:在Awake中一次性获取组件,避免冗余操作。
  • 物理逻辑分离:移动逻辑放到FixedUpdate中,符合Unity物理更新的帧同步规则。
  • 跳跃逻辑优化:单独封装Jump方法,保留X轴速度,避免覆盖移动状态,同时让逻辑更清晰。
  • 双跳重置:只要落地就重置双跳,逻辑更严谨,避免因按住空格导致无法重置的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:10:22