目录
🟥 欧拉旋转 与 四元数旋转的对比
1️⃣ 欧拉旋转
2️⃣ 四元数旋转
🟧 四元数旋转方法
1️⃣ Dotween,插值到目标欧拉角
2️⃣ Quaternion.Slerp,插值到目标欧拉角
3️⃣ Rotate,绕自身坐标系旋转
4️⃣ Rotate,绕世界坐标系旋转
🟨 四元数和欧拉角的相互转换
1️⃣ 四元数转化成欧拉角
2️⃣ 欧拉角转换成四元数
本节为Unity万向锁系列的最后一节,
这一节我们就来解决这个难题:使用四元数旋转,避免Unity万向锁。
🟥 欧拉旋转 与 四元数旋转的对比
1️⃣ 欧拉旋转
代码示例:
private void Update(){transform.eulerAngles+=new Vector3(1,1,1);}
优点:
- 很容易理解,形象直观;
- 表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;
缺点:
- 之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
- 会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴;
- 由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
代码:
if (Input.GetKeyDown(KeyCode.C)){transform.localEulerAngles=Vector3.zero;transform.DOLocalRotate(new Vector3(90, 90, 90), 0.5f);}
2️⃣ 四元数旋转
优点:
- 可以避免万向节锁现象;
- 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
- 可以提供平滑插值;
代码:
if (Input.GetKeyDown(KeyCode.C)){transform.localEulerAngles = Vector3.zero;transform.DOLocalRotateQuaternion(Quaternion.Euler(new Vector3(90, 90, 90)), 0.5f);//或者:transform.Rotate(new Vector3(0, 90, 0));}
缺点:
- 比欧拉旋转稍微复杂了一点点,因为多了一个维度;
- 理解更困难,不直观;
🟧 四元数旋转方法
1️⃣ Dotween,插值到目标欧拉角
Dotween的四元数旋转,是先将要旋转到的目标欧拉角,转化为四元数,
再进行旋转。
举例:
transform.DOLocalRotateQuaternion(Quaternion.Euler(new Vector3(90, 90, 90)), 0.5f);
2️⃣ Quaternion.Slerp,插值到目标欧拉角
先将欧拉角转化为四元数,
再插值运算到目标欧拉角。
public float rotateSpeed &#61; 2f;Quaternion targetAngels;private void Start(){targetAngels &#61; Quaternion.Euler(0, 90f, 0);}void Update(){// 用 slerp 进行插值平滑的旋转transform.rotation &#61; Quaternion.Slerp(transform.rotation, targetAngels, rotateSpeed * Time.deltaTime);// 当初始角度跟目标角度小于1,将目标角度赋值给初始角度,让旋转角度是我们需要的角度if (Quaternion.Angle(targetAngels, transform.rotation) <1){transform.rotation &#61; targetAngels;}}
3️⃣ Rotate&#xff0c;绕自身坐标系旋转
将物体&#xff0c;绕自身的动态坐标系&#xff0c;旋转x角度。
举例&#xff1a;
transform.Rotate(new Vector3(0, 90, 0));
//或者&#xff1a;
transform.Rotate(0, 90, 0, Space.Self);
//或者&#xff1a;
transform.Rotate(new Vector3(0, 90, 0), Space.Self);
4️⃣ Rotate&#xff0c;绕世界坐标系旋转
将物体&#xff0c;绕世界的静态坐标系&#xff0c;旋转x角度。
举例&#xff1a;
transform.Rotate(90, 0, 0, Space.World);
//或者&#xff1a;
transform.Rotate(new Vector3(0, 90, 0), Space.World);
&#x1f7e8; 四元数和欧拉角的相互转换
1️⃣ 四元数转化成欧拉角
Vector3 v3&#61;transform.rotation.eulerAngles;
2️⃣ 欧拉角转换成四元数
Quaternion rotation &#61; Quaternion.Euler(v3);
大家还有什么问题&#xff0c;欢迎在下方留言&#xff01;
如果你有 技术的问题 或 项目开发
都可以加下方联系方式
和我聊一聊你的故事&#x1f9e1;