Unity中如何阻止Player在鼠标操作时出现非预期斜向/水平位移?
Unity角色控制意外位移问题解决方案
问题根源
你的代码存在两个核心问题:
- 角色俯仰旋转导致移动方向偏移:
rotate()函数中让角色绕自身X轴旋转(鼠标上下移动),当角色抬头/低头后,transform.rotation * move会把原本的水平移动向量带向Z轴方向,最终通过CharacterController.Move()产生斜向位移。 - 重复的Y轴移动操作:
Movement()中同时用了move.y = JumpSpeed和transform.Translate(Vector3.up...),两种移动逻辑冲突,可能导致异常位移。
有效解决办法
1. 分离角色与相机的旋转逻辑
角色只负责左右旋转(鼠标X轴),上下旋转交给挂载在角色子物体上的相机,这样角色始终保持水平姿态,不会因为俯仰改变移动方向。
2. 修正移动逻辑
- 移除
Movement()中多余的transform.Translate调用,完全通过CharacterController.Move()处理所有移动。 - 基于相机的水平方向计算移动向量,确保移动始终贴合地面平面。
3. 限制相机俯仰角度(可选但推荐)
用Mathf.Clamp限制相机的X轴旋转角度,避免过度抬头/低头导致视角异常。
修改后的代码示例
private CharacterController myCharController; [Header("Character Settings")] [SerializeField] private float playerSpeed = 5.0f; [SerializeField] private float turnSpeed = 20f; [SerializeField] private float runningSpeed = 7.0f; [SerializeField] private float jumpSpeed = 7.0f; private const float gravity = 25.0f; private Vector3 move; // 引用相机,在Inspector面板拖入角色头部的相机对象 [SerializeField] private Camera playerCamera; void Start() { myCharController = GetComponent<CharacterController>(); move = Vector3.zero; } void Update() { Movement(); RotateCharacter(); RotateCamera(); } void Movement() { if (myCharController.isGrounded) { // 获取玩家输入 float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); // 提取相机的水平前向与侧向(剔除Y轴分量,保证移动在水平面) Vector3 cameraForward = Vector3.Scale(playerCamera.transform.forward, new Vector3(1, 0, 1)).normalized; Vector3 cameraRight = playerCamera.transform.right; // 计算最终移动方向并标准化(避免斜向移动速度过快) move = (vertical * cameraForward + horizontal * cameraRight).normalized; // 切换跑步/行走速度 move *= Input.GetKey(KeyCode.LeftShift) ? runningSpeed : playerSpeed; if (Input.GetButtonDown("Jump")) { move.y = jumpSpeed; } } // 持续应用重力 move.y -= gravity * Time.deltaTime; // 执行角色移动 myCharController.Move(move * Time.deltaTime); } void RotateCharacter() { // 角色仅绕Y轴旋转,跟随鼠标左右移动 float mouseX = Input.GetAxis("Mouse X") * turnSpeed * Time.deltaTime; transform.Rotate(0, mouseX, 0); } void RotateCamera() { // 相机绕自身X轴旋转,用Mathf.Clamp限制俯仰角度(-60到60度) float mouseY = Input.GetAxis("Mouse Y") * turnSpeed * Time.deltaTime; Vector3 currentRotation = playerCamera.transform.localEulerAngles; // 将角度转换为-180~180范围,方便 clamp 处理 float xRotation = currentRotation.x > 180 ? currentRotation.x - 360 : currentRotation.x; xRotation = Mathf.Clamp(xRotation - mouseY, -60f, 60f); // 转换回0~360范围赋值给相机 currentRotation.x = xRotation < 0 ? xRotation + 360 : xRotation; playerCamera.transform.localEulerAngles = currentRotation; }
关键说明
- 相机需要设置为角色的子物体,初始位置调整到角色头部合理位置。
Vector3.Scale用于剔除相机前向的Y轴分量,确保移动始终保持在水平面上。Mathf.Clamp在这里主要用于限制相机俯仰角度,避免视角翻转,同时彻底解决了因角色俯仰导致的位移异常问题。
内容的提问来源于stack exchange,提问作者Noblesse
相关产品推荐
相关产品推荐

