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

如何基于自身坐标系而非全局坐标系旋转物体并限制旋转范围

优化后的Unity自身轴旋转带角度限制实现方案

核心思路

  • 维护独立的总旋转累积变量,替代直接修改transform.rotation,便于精准控制旋转范围
  • 通过Quaternion.Euler将累积旋转值转换为四元数,实现基于物体自身轴的旋转逻辑
  • 对每个轴的总旋转值单独做范围限制,确保旋转始终在设定区间内

优化后代码

[Header("Camera Rotation Settings")]
[SerializeField] private Vector2 _yawMinMax = new Vector2(-180f, 180f); // Y轴左右旋转范围
[SerializeField] private Vector2 _pitchMinMax = new Vector2(-90f, 90f); // X轴上下旋转范围
[SerializeField] private Vector2 _rollMinMax = new Vector2(-25f, 25f);   // Z轴倾斜旋转范围
[SerializeField] private float _mouseYawSensitivity = 2f;
[SerializeField] private float _mousePitchSensitivity = 2f;
[SerializeField] private float _rollSensitivity = 5f;

private float _currentYaw;
private float _currentPitch;
private float _currentRoll;

void Start()
{
    Cursor.lockState = CursorLockMode.Locked;
    // 继承物体初始旋转角度,避免旋转从零开始的突兀感
    Vector3 initialEuler = transform.eulerAngles;
    _currentYaw = initialEuler.y;
    _currentPitch = initialEuler.x;
    _currentRoll = initialEuler.z;
}

void Update()
{
    UpdateRotation();
}

private void UpdateRotation()
{
    // 处理鼠标输入的左右/上下旋转
    float mouseX = Input.GetAxis("Mouse X") * _mouseYawSensitivity * Time.deltaTime * 100f;
    float mouseY = Input.GetAxis("Mouse Y") * _mousePitchSensitivity * Time.deltaTime * 100f;

    _currentYaw += mouseX;
    _currentPitch -= mouseY; // 反转Y轴输入,匹配常规视角控制逻辑

    // 强制限制旋转范围
    _currentYaw = Mathf.Clamp(_currentYaw, _yawMinMax.x, _yawMinMax.y);
    _currentPitch = Mathf.Clamp(_currentPitch, _pitchMinMax.x, _pitchMinMax.y);

    // 处理Q/E键控制的倾斜旋转
    if (Input.GetKey(KeyCode.Q))
    {
        _currentRoll += _rollSensitivity * Time.deltaTime * 50f;
    }
    else if (Input.GetKey(KeyCode.E))
    {
        _currentRoll -= _rollSensitivity * Time.deltaTime * 50f;
    }
    // 无输入时自动平滑回正倾斜角度
    else
    {
        if (_currentRoll > 0)
        {
            _currentRoll = Mathf.Max(0, _currentRoll - _rollSensitivity * Time.deltaTime * 80f);
        }
        else if (_currentRoll < 0)
        {
            _currentRoll = Mathf.Min(0, _currentRoll + _rollSensitivity * Time.deltaTime * 80f);
        }
    }
    _currentRoll = Mathf.Clamp(_currentRoll, _rollMinMax.x, _rollMinMax.y);

    // 将累积旋转值转换为四元数,赋值给物体旋转
    transform.rotation = Quaternion.Euler(_currentPitch, _currentYaw, _currentRoll);
}

关键改进点

  • 精准范围控制:直接限制总旋转角度而非旋转增量,彻底解决原代码中范围限制失效的问题
  • 简洁逻辑:移除原代码中重复赋值transform.rotation的冗余操作,优化Roll轴回正逻辑
  • 初始状态继承:读取物体初始欧拉角作为旋转起点,保持场景内初始旋转设置
  • 清晰命名:采用Yaw/Pitch/Roll的通用3D旋转术语,提升代码可读性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:22:06