Unity中2D角色仅能向上向左移动,无法向下向右的问题求助
问题
编写TopDownMovementScript测试脚本时遇到异常:游戏运行时角色可正常向上、向左移动,但无法向下、向右移动,Unity控制台无报错或警告。移除moveDown和moveLeft的负号后,向下、向右移动恢复正常,但速度明显快于向上、向左。
原代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TopDownMovementScript : MonoBehaviour { public float speed = 10; Vector3 moveUp = Vector3.zero; Vector3 moveDown = Vector3.zero; Vector3 moveLeft = Vector3.zero; Vector3 moveRight = Vector3.zero; public float rigidbody2DYPosition = 0; public float rigidbody2DXPosition = 0; public Rigidbody2D rb; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { rigidbody2DYPosition = rb.position.y; rigidbody2DXPosition = rb.position.x; moveUp = new Vector3(rb.position.x, rigidbody2DYPosition += speed); moveDown = new Vector3(rb.position.x, rigidbody2DYPosition += -speed); moveLeft = new Vector3(rigidbody2DXPosition += -speed, rb.position.y); moveRight = new Vector3(rigidbody2DXPosition += speed, rb.position.y); if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) { rb.MovePosition(moveUp); } if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) { rb.MovePosition(moveDown); } if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) { rb.MovePosition(moveLeft); } if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) { rb.MovePosition(moveRight); } Debug.Log(moveDown); Debug.Log(moveRight); }
解决方案
问题根源
- 变量赋值覆盖:计算
moveUp时使用rigidbody2DYPosition += speed,直接修改了该变量的原始值。后续计算moveDown时,用的是已经被moveUp修改后的Y值,再减去speed等于回到初始Y值,导致向下移动无效果。同理,moveLeft修改rigidbody2DXPosition后,moveRight的计算也会被干扰。 - 未做帧率适配:直接用
speed作为位移量,不同帧率下移动速度会不一致,修改负号后的速度差异本质也是变量覆盖导致的位移计算错误。
重构修复方案(推荐)
改用Unity输入轴API,同时加入Time.deltaTime保证帧率无关的稳定移动:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TopDownMovementScript : MonoBehaviour { public float speed = 10f; public Rigidbody2D rb; void Update() { // 获取标准化输入轴,自动适配WASD和方向键 float inputX = Input.GetAxis("Horizontal"); float inputY = Input.GetAxis("Vertical"); // 计算移动方向,避免斜向移动速度过快 Vector2 moveDir = new Vector2(inputX, inputY).normalized; // 计算目标位置,乘以Time.deltaTime保证不同帧率下速度一致 Vector2 targetPos = rb.position + moveDir * speed * Time.deltaTime; rb.MovePosition(targetPos); } }
保留原结构的修复方案
如果想维持原有变量结构,需避免修改原始位置变量,直接基于当前位置计算目标点:
void Update() { float currentY = rb.position.y; float currentX = rb.position.x; // 直接基于当前位置计算,不修改原始变量 moveUp = new Vector3(currentX, currentY + speed * Time.deltaTime); moveDown = new Vector3(currentX, currentY - speed * Time.deltaTime); moveLeft = new Vector3(currentX - speed * Time.deltaTime, currentY); moveRight = new Vector3(currentX + speed * Time.deltaTime, currentY); if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) { rb.MovePosition(moveUp); } if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) { rb.MovePosition(moveDown); } if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) { rb.MovePosition(moveLeft); } if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) { rb.MovePosition(moveRight); } }
内容的提问来源于stack exchange,提问作者Stelbert Stylton
相关产品推荐
相关产品推荐

