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

Unity 2D游戏中玩家空中未按移动键仍持续移动问题排查

Unity 2D玩家空中松开移动键后持续移动的问题修复

我正在制作一款Unity 2D游戏,玩家可跳跃、左右移动,且支持空中变向,但当前存在问题:玩家松开移动按键后,在空中仍会沿跳跃时的方向持续移动。

以下是原移动脚本:

public float jumpHeight;

public float speed;

public Rigidbody2D rb;

private bool isGrounded;

public Transform feetPos;

public float checkRadius;

public LayerMask Ground;

private float jumpTimeCounter;

public float jumpTime;

private bool isJumping;

void Update()
{
    PausedThisFrame = false;

    isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, Ground);

    if (isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        isJumping = true;
        jumpTimeCounter = jumpTime;
        rb.velocity = Vector2.up * jumpHeight;
    }
    if (Input.GetKey(KeyCode.Space) && isJumping)
    {
        if (jumpTimeCounter > 0)
        {
            rb.velocity = Vector2.up * jumpHeight;
            jumpTimeCounter -= Time.deltaTime;
        }
        else
        {
            isJumping = false;
        }
    }
    if (Input.GetKeyUp(KeyCode.Space))
    {
        isJumping = false;
    }
}

void FixedUpdate()
{
    if (Input.GetKey(KeyCode.A))
    {
        Debug.Log("A");
        rb.velocity = new Vector2(-1 * speed, rb.velocity.y);
        transform.eulerAngles = new Vector3(0, 180, 0);
    }
    if (Input.GetKey(KeyCode.D))
    {
        Debug.Log("D");
        rb.velocity = new Vector2(1 * speed, rb.velocity.y);
        transform.eulerAngles = new Vector3(0, 0, 0);
    }
    else
    {
        rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
    }
}

我已尝试调试代码,确认脚本未检测到按键输入,但仍不清楚是什么在改变Rigidbody2D的速度。


问题根源

原FixedUpdate的逻辑存在分支漏洞:

  • 当按下A键时设置左移速度,按下D键时设置右移速度,但else分支仅属于Input.GetKey(KeyCode.D)的判断。
  • 当松开A键且未按D键时,两个if判断都不触发,rb.velocity.x会保留之前的数值;如果Rigidbody2D的Linear Drag为0,物理体将保持该速度持续移动。
  • 直接给rb.velocity.x赋值固定速度的方式,也忽略了物理特性的连贯性。

修复后的脚本

public float jumpHeight;
public float speed;
public Rigidbody2D rb;
private bool isGrounded;
public Transform feetPos;
public float checkRadius;
public LayerMask Ground;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
// 空中减速系数:0=立即停止,0~1=逐渐减速(按需调整)
public float airDrag = 0f;

void Update()
{
    bool PausedThisFrame = false;

    isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, Ground);

    if (isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        isJumping = true;
        jumpTimeCounter = jumpTime;
        rb.velocity = Vector2.up * jumpHeight;
    }
    if (Input.GetKey(KeyCode.Space) && isJumping)
    {
        if (jumpTimeCounter > 0)
        {
            rb.velocity = Vector2.up * jumpHeight;
            jumpTimeCounter -= Time.deltaTime;
        }
        else
        {
            isJumping = false;
        }
    }
    if (Input.GetKeyUp(KeyCode.Space))
    {
        isJumping = false;
    }
}

void FixedUpdate()
{
    // 统一获取水平输入:-1(A)、0(无输入)、1(D)
    float horizontalInput = Input.GetAxisRaw("Horizontal");

    if (horizontalInput != 0)
    {
        // 有输入时设置移动速度
        rb.velocity = new Vector2(horizontalInput * speed, rb.velocity.y);
        // 自动翻转角色朝向
        transform.eulerAngles = new Vector3(0, horizontalInput > 0 ? 0 : 180, 0);
    }
    else
    {
        if (isGrounded)
        {
            // 地面松开按键立即停止
            rb.velocity = new Vector2(0, rb.velocity.y);
        }
        else
        {
            // 空中松开按键应用减速(可替换为0实现立即停止)
            rb.velocity = new Vector2(rb.velocity.x * (1 - airDrag), rb.velocity.y);
        }
    }
}

关键修改说明

  1. 使用Input.GetAxisRaw("Horizontal")统一处理水平输入,避免原分支逻辑的漏洞。
  2. 区分地面/空中的停止逻辑:地面上立即停,空中可选择立即停或逐渐减速(通过airDrag参数调整手感)。
  3. 自动根据输入方向翻转角色朝向,简化原逻辑。

额外注意

  • 检查Rigidbody2D组件的Linear Drag参数,若值为0会让物理体保持速度不变;若需要自然的空中减速,可适当提高该值。
  • 原代码中PausedThisFrame变量未定义,建议确认是否有相关逻辑遗漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:01:05