目录
一、什么是四元数
二、和欧拉角的关联以及为什么会出现四元数
三、四元数的基本组成
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("当前旋转与反向旋转对齐");
}
操作 | 数学本质 | Unity中的作用 | 典型场景 |
---|---|---|---|
乘法(×) | 旋转叠加(顺序敏感) | 组合多个旋转,或转换坐标系 | 角色转身+抬头、动画叠加 |
点乘(Dot) | 四维空间中的夹角余弦 | 检测旋转相似度、判断旋转完成或反向 | 插值优化、AI朝向检测、反向动作触发 |
综合对比:
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 | 计算两个四元数的四维点积,用于判断旋转相似度(1为相同,-1为反向)。 |