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

Unity中如何解决角色绕错误轴旋转的问题?

问题分析与修复方案

你的鼠标控制异常核心问题在于旋转逻辑的应用对象和轴映射错误,同时移动代码存在冗余和时间步不一致的问题,下面逐一修复:

核心旋转问题修复

你需要明确区分两种旋转逻辑:

  • 鼠标左右移动(Mouse X):控制角色身体绕Y轴旋转(左右转向)
  • 鼠标上下移动(Mouse Y):控制视角(如相机)绕X轴旋转(抬头低头),而非角色本身

你的代码直接修改角色的transform.eulerAngles,导致鼠标上下移动时角色身体跟着俯仰,同时用Vector2给Vector3类型的欧拉角赋值,会丢失Z轴旋转数据。

修正后的旋转逻辑

假设你的相机是角色的子物体(第一人称视角常用设置),调整旋转代码如下:

// 在类中添加相机引用
public Camera playerCamera;

void FixedUpdate()
{
    // ... 保留移动逻辑,先修复移动问题 ...

    // 角色左右转向:Mouse X控制Y轴旋转
    float bodyTurn = Input.GetAxis("Mouse X") * turnSpeed;
    transform.Rotate(0, bodyTurn, 0);

    // 视角上下俯仰:Mouse Y控制相机X轴旋转
    rotX += Input.GetAxis("Mouse Y") * turnSpeed;
    rotX = Mathf.Clamp(rotX, minTurnAngle, maxTurnAngle);
    playerCamera.transform.localEulerAngles = new Vector3(-rotX, 0, 0);
}

移动逻辑的冗余与时间步修复

原移动代码存在两处问题:

  1. 重复计算移动向量,且两个if判断会导致输入同时触发时重复执行移动
  2. 时间步不一致:混用Time.fixedDeltaTime和Time.deltaTime,FixedUpdate中应统一使用Time.fixedDeltaTime

修正后的移动逻辑

void FixedUpdate()
{
    float horizontal = Input.GetAxis("Horizontal");
    float vertical = Input.GetAxis("Vertical");
    // 合并输入判断,无需分开检测Vertical和Horizontal
    if (horizontal != 0 || vertical != 0)
    {
        Vector3 moveDir = new Vector3(horizontal, 0.0f, vertical);
        // 转换为本地空间方向,确保角色朝向与移动方向匹配
        moveDir = transform.TransformDirection(moveDir);
        Physics.MovePosition(transform.position + moveDir * speed * Time.fixedDeltaTime);
    }

    // ... 旋转逻辑 ...
}

完整修正后的代码

using UnityEngine;

public class Movement : MonoBehaviour // 类名遵循C#大驼峰命名规范
{
    // 配置变量
    public float speed = 5.0f;
    public float turnSpeed = 4.0f;
    public float minTurnAngle = -90.0f;
    public float maxTurnAngle = 90.0f;
    private float rotX;

    // 组件引用
    public Camera playerCamera;
    private Rigidbody rb; // 变量名更清晰直观

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        // 自动获取主相机(未手动赋值时)
        if (playerCamera == null)
            playerCamera = Camera.main;
    }

    void FixedUpdate()
    {
        // 移动逻辑
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        if (horizontal != 0 || vertical != 0)
        {
            Vector3 moveDir = new Vector3(horizontal, 0, vertical);
            moveDir = transform.TransformDirection(moveDir);
            rb.MovePosition(transform.position + moveDir * speed * Time.fixedDeltaTime);
        }

        // 旋转逻辑
        float bodyTurn = Input.GetAxis("Mouse X") * turnSpeed;
        transform.Rotate(0, bodyTurn, 0);

        rotX += Input.GetAxis("Mouse Y") * turnSpeed;
        rotX = Mathf.Clamp(rotX, minTurnAngle, maxTurnAngle);
        playerCamera.transform.localEulerAngles = new Vector3(-rotX, 0, 0);
    }
}

额外优化建议

  • 给角色的Rigidbody组件勾选Freeze Rotation X和Freeze Rotation Z,避免物理模拟干扰角色旋转
  • 添加鼠标锁定逻辑(Cursor.lockState = CursorLockMode.Locked),提升第一人称视角操作体验
  • 遵循C#命名规范,类名用大驼峰、变量名用小驼峰,提高代码可读性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:35