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); } } }
关键修改说明
- 使用
Input.GetAxisRaw("Horizontal")统一处理水平输入,避免原分支逻辑的漏洞。 - 区分地面/空中的停止逻辑:地面上立即停,空中可选择立即停或逐渐减速(通过
airDrag参数调整手感)。 - 自动根据输入方向翻转角色朝向,简化原逻辑。
额外注意
- 检查Rigidbody2D组件的Linear Drag参数,若值为0会让物理体保持速度不变;若需要自然的空中减速,可适当提高该值。
- 原代码中
PausedThisFrame变量未定义,建议确认是否有相关逻辑遗漏。
内容的提问来源于stack exchange,提问作者Vota
相关产品推荐
相关产品推荐

