Unity入门学习(四)3D数学(4)之四元数Quaternion_unity quaternion
目录
一、什么是四元数
二、和欧拉角的关联以及为什么会出现四元数
三、四元数的基本组成
Unity中的表示:
四、四元数Quaternion这个类中具有的属性和方法
常用属性
核心方法
五、四元数之间的计算
1. 叉乘(组合旋转)
2. 点积(相似度)
六、总结
四元数 Quaternion 属性与方法总结
详细说明
1. 属性
2. 方法
3. 运算符与静态方法
一、什么是四元数
定义
四元数(Quaternion)是一种数学工具,用于表示三维空间中的旋转。它由四个分量组成:一个实部(w)和三个虚部(x, y, z),数学表达式为:
q=w+xi+yj+zk
其中
你可以想象四元数是一个“方向标记”,而欧拉角是“分解成三个步骤的转动角度”。四元数通过一种紧凑的数学形式直接描述方向,避免了欧拉角的分步旋转可能导致的万向节死锁问题。
Unity中的应用
在Unity中,所有Transform组件的旋转底层均由四元数实现。虽然开发者通常通过欧拉角(如Inspector面板中的Rotation)调整物体朝向,但Unity会自动将其转换为四元数存储。
二、和欧拉角的关联以及为什么会出现四元数
欧拉角的局限性
万向节死锁(Gimbal Lock):当绕某一轴旋转90度时,另外两个轴的旋转会重合,导致丢失一个自由度。就是说当你转到90度时,你想单独再沿着某一条轴进行旋转,发现怎么都不可以
例如:飞机俯仰90度后,偏航和滚转将绕同一轴旋转,无法独立控制。
插值不平滑:直接对欧拉角插值会导致旋转路径不自然(如抖动或突变)。
四元数的优势
无万向节死锁:四元数通过四维空间描述旋转,避免了三维欧拉角的轴顺序问题。
平滑插值:支持球面线性插值(Slerp),保证旋转路径的最短性和平滑性。
计算高效:旋转合成和逆运算更高效,适合实时计算。
关联
转换关系:欧拉角可通过Quaternion.Euler()转换为四元数,反之通过Quaternion.eulerAngles属性获取。
三、四元数的基本组成
四元数构成
一个四元数包含一个标量和一个3D向量
[w,v],w为标量,v为3D向量
[w,(x,y,z)]
对于给定的任意的一个四元数:
表示3D空间中的一个旋转量
轴-角对
在3D空间中 任意旋转都可以表示 绕着某个轴旋转一个旋转角得到注意:该轴并不是空间中的xyz中轴 而是任意一个轴
对于给定旋转 假设为绕着n轴 旋转β角度 n轴为(x,y,z)
那么可以构成的四元数为:
四元数Q = [cos(β/2),sin(β/2)n]
四元数Q = [cos(β/2,sin(β/2)x,sin(β/2)y,sin(β/2)z]四元数Q则表示绕着轴n,旋转β度的旋转量
单位四元数
单位四元数表示没有旋转量(角位移)
当角度为0或者360度时
对于给定的轴都会得到单位四元数[1,(0,0,0)]和[-1,(0,0,0)]都是单位四元数
表示没有旋转量
Unity中的表示:
Quaternion q = new Quaternion(x, y, z, w);
// 注意:Unity的构造函数参数顺序为(x, y, z, w)
例如:绕Y轴旋转90度的四元数:
Quaternion rotation = Quaternion.Euler(0, 90, 0);// 等效于手动计算:float angle = 90 * Mathf.Deg2Rad;Quaternion q = new Quaternion(0, Mathf.Sin(angle/2), 0, Mathf.Cos(angle/2));
四、四元数Quaternion这个类中具有的属性和方法
常用属性
identity
eulerAngles
核心方法
AngleAxis
Quaternion.AngleAxis(90, Vector3.up)
Euler
Quaternion.Euler(0, 90, 0)
Slerp
Quaternion.Slerp(a, b, t)
Lerp
Quaternion.Lerp(a, b, t)
Inverse
Quaternion.Inverse(rotation)
LookRotation
Quaternion.LookRotation(direction)
详细解释:
属性:
(1)identity:单位四元数(无旋转)
表示“不旋转”的状态,常用于初始化旋转或重置物体方向。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ void Start() { // 将物体旋转重置为初始状态(无旋转) transform.rotation = Quaternion.identity; }}
(2)eulerAngles:将四元数转换为欧拉角
返回当前四元数对应的欧拉角(只读属性),常用于调试或显示直观角度。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ void Update() { // 实时输出物体的欧拉角 Debug.Log(\"当前欧拉角:\" + transform.rotation.eulerAngles); // 注意:直接修改 eulerAngles 可能导致问题,应通过 Quaternion.Euler() 设置 // transform.eulerAngles = new Vector3(0, 90, 0); // 不推荐 }}
方法:
(1) AngleAxis:绕指定轴旋转指定角度
创建绕某个轴旋转一定角度的四元数,常用于自由轴旋转。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ public float rotateSpeed = 90f; // 每秒旋转90度 void Update() { // 绕Y轴旋转(按每秒 rotateSpeed 度旋转) float angle = rotateSpeed * Time.deltaTime; Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.up); transform.rotation = rotation * transform.rotation; }}
(2) Euler:欧拉角转四元数
将欧拉角转换为四元数,避免直接操作 eulerAngles 导致的问题。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ void Start() { // 设置物体绕Y轴旋转90度 Quaternion targetRotation = Quaternion.Euler(0, 90, 0); transform.rotation = targetRotation; }}
(3) Slerp:球面线性插值
沿球面最短路径平滑插值,适合摄像机跟踪或自然旋转。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ public Transform target; // 拖入目标物体 public float speed = 0.5f; void Update() { // 计算目标方向 Vector3 direction = target.position - transform.position; Quaternion targetRotation = Quaternion.LookRotation(direction); // 使用Slerp平滑旋转 transform.rotation = Quaternion.Slerp( transform.rotation, targetRotation, speed * Time.deltaTime ); }}//先快后慢//A.rotation = Quaternion.Slerp(A.rotation,target.rotation,Time.deltaTime);//匀速变化//time += Time.deltaTime;//B.rotation = Quaternion.Slerp(start,target.rotation,time);
效果:物体会平滑转向目标物体,路径无抖动。
(4) Lerp:线性插值
快速插值但路径非最短,适合对平滑性要求不高的场景。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ public Transform target; public float speed = 1f; void Update() { Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position); transform.rotation = Quaternion.Lerp( transform.rotation, targetRotation, speed * Time.deltaTime ); }}
(5) Inverse:反向旋转
获取当前旋转的逆旋转,常用于坐标系转换或相对旋转。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ public Transform otherObject; void Update() { // 计算当前旋转的逆旋转 Quaternion inverseRotation = Quaternion.Inverse(transform.rotation); // 将另一个物体的旋转设置为当前物体的逆旋转 otherObject.rotation = inverseRotation; }}
效果:otherObject
会始终与当前物体保持反向旋转。
(6) LookRotation:朝向某个方向
使物体正面朝向指定方向,常用于控制角色或摄像机。
using UnityEngine;public class QuaternionExample : MonoBehaviour{ public Vector3 targetDirection = Vector3.forward; // 默认朝前 void Update() { // 动态让物体朝向 targetDirection 方向 Quaternion targetRotation = Quaternion.LookRotation(targetDirection); transform.rotation = targetRotation; }}
效果:物体正面始终指向 targetDirection
(可修改为鼠标或目标位置)。
完整臻享版:
using UnityEngine;public class QuaternionDemo : MonoBehaviour{ public Transform target; public float rotateSpeed = 90f; public float slerpSpeed = 0.5f; void Start() { // 初始化无旋转 transform.rotation = Quaternion.identity; } void Update() { // 1. AngleAxis 持续绕Y轴旋转 float angle = rotateSpeed * Time.deltaTime; Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.up); transform.rotation = rotation * transform.rotation; // 2. LookRotation 朝向目标 if (target != null) { Vector3 direction = target.position - transform.position; Quaternion targetRot = Quaternion.LookRotation(direction); transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, slerpSpeed * Time.deltaTime); } // 3. 输出当前欧拉角 Debug.Log(\"当前欧拉角:\" + transform.rotation.eulerAngles); }}
五、四元数之间的计算
1. 叉乘(组合旋转)
四元数乘法表示旋转的叠加,顺序为从右到左应用。
公式:
注意啊不满足交换律:即:
Quaternion qY = Quaternion.Euler(0, 90, 0); // 绕Y轴转90度Quaternion qX = Quaternion.Euler(90, 0, 0); // 绕X轴转90度// 顺序1:先绕Y轴转,再绕X轴转transform.rotation = qX * qY;// 顺序2:先绕X轴转,再绕Y轴转transform.rotation = qY * qX;/*效果:顺序1:物体会先面向右侧(Y轴旋转),然后向上翻转(X轴旋转)。顺序2:物体会先向上翻转(X轴旋转),然后面向右侧(Y轴旋转)。最终朝向完全不同(可通过运行代码观察)。*/
2. 点积(相似度)
四元数的点乘(Quaternion.Dot(q1, q2))返回值的范围是 [-1, 1],表示两个旋转的相似程度:
1:完全相同旋转。
-1:互为反向旋转。
0:旋转方向正交(无关)。
实际应用场景
(1) 判断旋转是否完成
Quaternion targetRotation = Quaternion.Euler(0, 90, 0);float similarity = Quaternion.Dot(transform.rotation, targetRotation);if (similarity > 0.999f) { Debug.Log(\"旋转完成!\");}
(2) 平滑过渡检测 在插值旋转时,若相似度接近1,可提前终止插值以优化性能:
Quaternion current = transform.rotation;Quaternion target = Quaternion.Euler(0, 90, 0);float t = Quaternion.Dot(current, target);if (t < 0.99f) { transform.rotation = Quaternion.Slerp(current, target, Time.deltaTime * speed);}
(3) 反向旋转检测
Quaternion inverse = Quaternion.Inverse(currentRotation);float similarity = Quaternion.Dot(currentRotation, inverse);if (similarity < -0.999f) { Debug.Log(\"当前旋转与反向旋转对齐\");}
综合对比:
using UnityEngine;public class QuaternionOperationsDemo : MonoBehaviour{ void Start() { // 1. 验证乘法顺序 Quaternion qY = Quaternion.Euler(0, 90, 0); Quaternion qX = Quaternion.Euler(90, 0, 0); Debug.Log(\"顺序1 (qX*qY): \" + (qX * qY).eulerAngles); // 输出 (90, 90, 0) Debug.Log(\"顺序2 (qY*qX): \" + (qY * qX).eulerAngles); // 输出 (90, 90, 270) // 2. 验证点乘相似度 Quaternion a = Quaternion.identity; Quaternion b = Quaternion.Euler(0, 90, 0); Quaternion c = Quaternion.Inverse(b); Debug.Log(\"a vs b: \" + Quaternion.Dot(a, b)); // 约0.7(不相似) Debug.Log(\"b vs b: \" + Quaternion.Dot(b, b)); // 1(完全一致) Debug.Log(\"b vs c: \" + Quaternion.Dot(b, c)); // -1(完全反向) }}
3. 逆运算
四元数的逆(Inverse
)表示反向旋转。
公式:
例如:
Quaternion inverse = Quaternion.Inverse(rotation);
这里同上,不再赘述
六、总结
四元数 Quaternion
属性与方法总结
identity
Quaternion
transform.rotation = Quaternion.identity;
eulerAngles
Vector3
(欧拉角)Vector3 angles = transform.rotation.eulerAngles;
AngleAxis
float angle
, Vector3 axis
Quaternion
Quaternion q = Quaternion.AngleAxis(90, Vector3.up);
Euler
float x
, float y
, float z
或 Vector3 euler
Quaternion
Quaternion q = Quaternion.Euler(0, 90, 0);
Slerp
Quaternion a
, Quaternion b
, float t
Quaternion
Quaternion.Slerp(current, target, Time.deltaTime * speed);
Lerp
Quaternion a
, Quaternion b
, float t
Quaternion
Quaternion.Lerp(current, target, Time.deltaTime * speed);
Inverse
Quaternion rotation
Quaternion
Quaternion inverse = Quaternion.Inverse(transform.rotation);
LookRotation
Vector3 forward
, Vector3 upwards=Vector3.up
(可选)Quaternion
Quaternion q = Quaternion.LookRotation(target.position - transform.position);
operator *
Quaternion a
, Quaternion b
(或 Vector3
向量)Quaternion
或 Vector3
Quaternion combined = q1 * q2;
Vector3 rotated = q * Vector3.forward;
Dot
Quaternion a
, Quaternion b
float
(相似度)float similarity = Quaternion.Dot(q1, q2);
详细说明
1. 属性
identity
new Quaternion(0, 0, 0, 1)
。eulerAngles
2. 方法
AngleAxis
Euler
Slerp
Lerp
Inverse
LookRotation
Vector3.up
为向上方向。3. 运算符与静态方法
operator *
Dot