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

Unity中如何阻止Player在鼠标操作时出现非预期斜向/水平位移?

Unity角色控制意外位移问题解决方案

问题根源

你的代码存在两个核心问题:

  1. 角色俯仰旋转导致移动方向偏移:rotate()函数中让角色绕自身X轴旋转(鼠标上下移动),当角色抬头/低头后,transform.rotation * move会把原本的水平移动向量带向Z轴方向,最终通过CharacterController.Move()产生斜向位移。
  2. 重复的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:17:54