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

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);
}

解决方案

问题根源

  1. 变量赋值覆盖:计算moveUp时使用rigidbody2DYPosition += speed,直接修改了该变量的原始值。后续计算moveDown时,用的是已经被moveUp修改后的Y值,再减去speed等于回到初始Y值,导致向下移动无效果。同理,moveLeft修改rigidbody2DXPosition后,moveRight的计算也会被干扰。
  2. 未做帧率适配:直接用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:53:16