如何基于自身坐标系而非全局坐标系旋转物体并限制旋转范围
优化后的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
相关产品推荐
相关产品推荐

