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); } }
关键修改说明
- 移动向量计算:通过
Player.right(玩家右侧方向)和Player.forward(玩家前方方向)构建移动向量,确保WASD对应玩家当前朝向的前后左右。 - 向量标准化:添加
normalized避免斜向移动时速度叠加导致移动过快。 - 时间增量修正:将
Time.deltaTime移到最后与速度相乘,保证移动速度帧率无关。 - 职责分离:移除
PlayerMovement中属于MouseLook的旋转相关变量,保持代码职责清晰。
内容的提问来源于stack exchange,提问作者David Rabinovich
相关产品推荐
相关产品推荐

