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

Unity中WASD移动与相机朝向不同步问题求助

问题:玩家WASD移动方向不随朝向改变

我编写了两个Unity脚本:MouseLook视角控制脚本和PlayerMovement玩家移动脚本。目前玩家可以正常旋转,但WASD按键的移动方向始终固定,不会随玩家朝向变化——比如按W键可能会向后、向左、向右或向前移动,完全取决于当前朝向。我希望玩家朝向哪个方向就向哪个方向移动,但尝试多种方法后仍未解决,代码中保留了多次尝试的注释。

原代码如下:

public class PlayerMovement : MonoBehaviour
{
public Transform Player;

public bool IsGrounded;
public CharacterController controller;
public float Speed = 12f;
Vector3 velocity;
public float gravity =-9.9f;
public Transform GroundCheck;
public float GroundDistance = .4f;
public LayerMask groundMask;
public float jumpheight = 2f;
private Vector3 rotation;
private float mouseSensitivity;
private float xRotation;
private float yRotation;



void Update()
{
    IsGrounded = Physics.CheckSphere(GroundCheck.position, GroundDistance, groundMask);

    if(IsGrounded && velocity.y < 0)
    {
        velocity.y = -2f;
    }
    this.rotation = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime);
    Vector3 move = this.rotation;
    //move = this.transform.InverseTransformDirection(move);
    controller.Move(move * Speed);
    //this.transform.Rotate(this.rotation);
     /*
    Vector3 move = new Vector3(Input.GetAxis("Horizontal") *Time.deltaTime, 0, Input.GetAxis("Vertical")*Time.deltaTime);
    this.transform.Rotate(move);
    //transform.TransformDirection(move * Speed * Time.deltaTime);
    //float x = Input.GetAxis("Horizontal");
    //float z = Input.GetAxis("Vertical");
    //Vector3 move = transform.right * x + transform.forward * z;
    controller.Move(move * Speed);
   
    //controller.transform.TransformDirection(move);
    // Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    //move = transform.TransformDirection(move);
    //controller.Move(move * Speed * Time.deltaTime);

    /*Vector3 move = transform.right * x + transform.forward*z;
           controller.Move(move * Speed * Time.deltaTime);
 //controller.transform.TransformDirection(move);
 controller.transform.TransformDirection(move);
   */ //controller.Move(move * Speed * Time.deltaTime);
    velocity.y += gravity * Time.deltaTime;
    controller.Move(velocity*Time.deltaTime);
    if(Input.GetButtonDown("Jump") && IsGrounded)
    {
        velocity.y = Mathf.Sqrt(jumpheight * -2 * gravity);
    }
}

 }

  public class MouseLook : MonoBehaviour
 {
float xRotation = 0f;
float yRotation = 0f;

public Transform Player;
public float mouseSensitivity = 100f;
// Start is called before the first frame update
void Start()
{
    Cursor.lockState = CursorLockMode.Locked;
}

// Update is called once per frame
void Update()
{
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity *Time.deltaTime;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
    xRotation -= mouseY;
    xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    yRotation += mouseX;
    transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0f);
    transform.TransformDirection(xRotation, yRotation, 0f);
    Player.Rotate(Vector3.up * mouseX);
  
}
 }

问题根源与修复方案

核心问题

PlayerMovement中移动向量的计算错误:直接使用Input.GetAxis生成的是世界空间的方向向量,没有结合玩家当前的朝向转换为本地空间方向,导致移动方向固定不随旋转变化。

修复后的PlayerMovement脚本

public class PlayerMovement : MonoBehaviour
{
    public Transform Player;
    public bool IsGrounded;
    public CharacterController controller;
    public float Speed = 12f;
    Vector3 velocity;
    public float gravity = -9.9f;
    public Transform GroundCheck;
    public float GroundDistance = .4f;
    public LayerMask groundMask;
    public float jumpheight = 2f;

    void Update()
    {
        // 地面检测逻辑保持不变
        IsGrounded = Physics.CheckSphere(GroundCheck.position, GroundDistance, groundMask);
        if (IsGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }

        // 正确计算基于玩家朝向的移动向量
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        // 使用玩家的right和forward方向构建本地空间移动向量
        Vector3 move = Player.right * horizontal + Player.forward * vertical;
        // 标准化向量避免斜向移动加速,乘以速度和时间增量
        controller.Move(move.normalized * Speed * Time.deltaTime);

        // 重力与跳跃逻辑保持不变
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
        if (Input.GetButtonDown("Jump") && IsGrounded)
        {
            velocity.y = Mathf.Sqrt(jumpheight * -2 * gravity);
        }
    }
}

额外优化(MouseLook脚本)

移除无效代码行transform.TransformDirection(xRotation, yRotation, 0f);,该方法需要传入向量而非欧拉角,此行无实际作用:

public class MouseLook : MonoBehaviour
{
    float xRotation = 0f;
    float yRotation = 0f;

    public Transform Player;
    public float mouseSensitivity = 100f;

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);
        yRotation += mouseX;

        // 相机上下旋转
        transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0f);
        // 玩家左右旋转
        Player.Rotate(Vector3.up * mouseX);
    }
}

关键修改说明

  1. 移动向量计算:通过Player.right(玩家右侧方向)和Player.forward(玩家前方方向)构建移动向量,确保WASD对应玩家当前朝向的前后左右。
  2. 向量标准化:添加normalized避免斜向移动时速度叠加导致移动过快。
  3. 时间增量修正:将Time.deltaTime移到最后与速度相乘,保证移动速度帧率无关。
  4. 职责分离:移除PlayerMovement中属于MouseLook的旋转相关变量,保持代码职责清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:45:06