目錄
一、什么是四元數
二、和歐拉角的關聯以及為什么會出現四元數
三、四元數的基本組成
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為反向)。 |
?