一、旋轉方法
在 Unity 中為物體旋轉提供了各種 API ,例如 RotateAround、Rotate、LookAt 等方法。但為了避免萬向節死鎖的問題,一般使用四元數來表示物體的旋轉。
四元數的乘法可以看作對一個物體施加兩次旋轉,最終的旋轉角度由這兩次旋轉的角度決定,旋轉的順序也會對旋轉的結果產生影響(Q1*Q2≠Q2*Q1),因為四元數乘法的本質就是矩陣的乘法。
二、世界坐標&局部坐標
物體的坐標分為世界坐標(global)和局部坐標(local)
-
世界旋轉坐標(如transform.rotation)表示物體相對於世界坐標系下的旋轉角度
-
局部旋轉坐標(如transform.localRotation)表示物體相對於父物體坐標系下的旋轉角度,如果沒有父物體,則局部旋轉坐標與世界旋轉坐標相同
另外,在 Inspector 面板中 Transform 的值也是物體的局部坐標。
三、世界坐標下的旋轉
利用四元數旋轉時要記住:旋轉軸屬於世界坐標系還是物體坐標系是由乘法的順序決定的。
所以
-
繞本地軸進行旋轉時:transform.rotation = transform.rotation * Quaternion;
-
繞世界軸進行旋轉時:transform.rotation = Quaternion * transform.rotation;
在這里不需要知道任何本地旋轉坐標或者對旋轉軸進行坐標系之間的轉換。
四、局部坐標下的旋轉
在局部坐標下的旋轉操作也是一樣的,只有旋轉順序決定了旋轉軸屬於世界坐標系還是物體坐標系:
-
繞本地軸進行旋轉:transform.localRotation = transform.localRotation * Quaternion;
-
繞世界軸進行旋轉:transform.localRotation = Quaternion * transform.localRotation;
對於繞本地軸的旋轉,在世界坐標以及局部坐標下進行操作的結果是相同的,而繞世界軸旋轉時,得到的結果是不一樣的。
因為這時物體的旋轉實際上可以分為兩個過程:
物體本地的旋轉(相對於父物體的旋轉)+ 父物體的旋轉,也就是 transform.rotation = transform.parent.transform.rotation * transform.localRotation。
五、旋轉實例
首先創建一個父物體 parentCube,兩個子物體 childCube1、childCube2。
1、本地軸旋轉
1 using UnityEngine; 2 3 public class QuaternionTest : MonoBehaviour 4 { 5 public Transform childCube1; 6 public Transform childCube2; 7 8 void Update() 9 { 10 Quaternion rotU = Quaternion.AngleAxis(100 * Time.deltaTime, Vector3.up); 11 childCube1.transform.rotation = childCube1.transform.rotation * rotU; 12 childCube2.transform.localRotation = childCube2.transform.localRotation * rotU; 13 } 14 }
右乘表示物體繞本地軸旋轉,所以 childCube 的旋轉是繞自身Y軸進行的,parentCube 的旋轉並不會對 childCube 旋轉產生影響,兩種方式旋轉相同。
2、世界軸旋轉
1 using UnityEngine; 2 3 public class QuaternionTest : MonoBehaviour 4 { 5 public Transform childCube1; 6 public Transform childCube2; 7 8 void Update() 9 { 10 Quaternion rotU = Quaternion.AngleAxis(200 * Time.deltaTime, Vector3.up); 11 childCube1.transform.rotation = rotU * childCube1.transform.rotation; 12 childCube2.transform.localRotation = rotU * childCube2.transform.localRotation; 13 } 14 }
左乘表示物體繞世界軸旋轉,在世界坐標下進行旋轉的時候無需考慮父物體的旋轉角度,導致 childCube1 最終旋轉軸是世界坐標系的Y軸。
而在局部坐標下進行旋轉的時候可以理解為先將父物體的旋轉角度置零,此時 childCube2 繞世界坐標系的Y軸旋轉,之后再進行父物體的旋轉,這樣就會導致物體旋轉軸隨着父物體改變而改變,換句話說就是物體本身的旋轉軸會指向父物體的Y軸。
3、rotation與localrotation的關系
物體的旋轉 = 物體相對於父物體的旋轉 + 父物體的旋轉,即 transform.rotation=transform.parent.transform.rotation * transform.localRotation
1 using UnityEngine; 2 3 public class QuaternionTest : MonoBehaviour 4 { 5 public Transform childCube1; 6 public Transform childCube2; 7 8 void Update() 9 { 10 Quaternion rotU = Quaternion.AngleAxis(200 * Time.deltaTime, Vector3.up); 11 childCube1.transform.rotation = childCube1.transform.parent.transform.rotation * rotU * childCube1.transform.localRotation; 12 childCube2.transform.localRotation = rotU * childCube2.transform.localRotation; 13 } 14 }
這兩個的旋轉軸相同,都是父物體的Y軸
六、總結
在使用四元數進行旋轉操作的時候要注意乘法的順序:左乘代表繞世界軸旋轉,右乘代表繞本地軸旋轉。
在對世界坐標和局部坐標進行右乘時二者會得到相同的結果,而進行左乘時則會得到不同的結果,根本的原因是對局部坐標操作時需要考慮父物體的旋轉,而對世界坐標操作時則不需要這種情況。
*** | 以上內容僅為學習參考、學習筆記使用 | ***