Unity – 旋轉方法

前言

本文梳理了Unity中常用的旋轉方法,涉及兩大類:Transform、Quaternion。

Transform 類

Rotate()

此方法重載多,易理解,在連續動態旋轉中較為常用。

/* 
    objsTrans[]為多物體的Transform組件,下標從1開始
    direction為(0,0,36)、Speed為1;
    初始時,1、2、4物體的rotation=(0,0,0),3、5、6物體的rotation=(180,0,0),其餘均為默認值
*/

// Rotate(Vector3 eulerAngles):以歐拉角旋轉
objsTrans[1].Rotate(direction * Speed * Time.fixedDeltaTime);

// Rotate(Vector3 axis, float angle):繞axis軸,旋轉angle度
objsTrans[2].Rotate(Vector3.forward, 36 * Speed * Time.fixedDeltaTime);

// Rotate(Vector3 eulerAngles, Space relativeTo):以歐拉角旋轉,但參照的是本地坐標系
objsTrans[3].Rotate(direction * Speed * Time.fixedDeltaTime, Space.Self);

// Rotate(float xAngle, float yAngle, float zAngle):繞各軸旋轉 X angle度
objsTrans[4].Rotate(0, 0, 36 * Speed * Time.fixedDeltaTime);

// Rotate(Vector3 axis, float angle, Space relativeTo):繞axis軸,旋轉angle度,但參照的是本地坐標系
objsTrans[5].Rotate(Vector3.forward, 36 * Speed * Time.fixedDeltaTime, Space.Self);

// Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo):繞各軸旋轉 X angle度,但參照的是本地坐標
objsTrans[6].Rotate(0, 0, 36 * Speed * Time.fixedDeltaTime, Space.Self);

RotateAround()

// RotateAround(Vector3 point, Vector3 axis, float angle):繞穿過世界坐標中的 point 的 axis 旋轉 angle 度
objsTrans[1].RotateAround(Vector3.zero, Vector3.forward, 36 * Speed * Time.fixedDeltaTime);

eulerAngles

以歐拉角表示的旋轉(以度為單位),是一個 Vector3類型的屬性

// 設定物體的歐拉角(本質為四元數)為 (0,0,90)
objsTrans[1].eulerAngles = new Vector3(0, 0, 90);

LookAt()

這是比較常用的一個旋轉類的函數,比如敵人、場景的AI等。其功能是 旋轉物體、使其z軸始終指向目標物體。target、worldPosition參數為目標物體資訊,worldUp參數較為特殊,涉及旋轉時自身坐標系與世界坐標系的約束問題(見下圖對比)。

LookAt(Transform target);
LookAt(Vector3 worldPosition);  
LookAt(Transform target, Vector3 worldUp = Vector3.up);  
LookAt(Vector3 worldPosition, Vector3 worldUp = Vector3.up);  

Quaternion 類

四元數用於表示旋轉,所有的 rotation都為Quaternion類型,沒有Vector3類型的 eulerAngles 直觀,但其不受萬向鎖影響,可以輕鬆插值運算。

eulerAngles

四元數的歐拉角形式,原有的轉換為歐拉角的方法如ToEuler()、ToEulerAngle()已被棄用。。

Quaternion quaternion = new Quaternion { eulerAngles = new Vector3(0, 0, 90) };
objsTrans[1].rotation = quaternion;   // 直接設定物體的rotation(即四元數)為 (0,0,90)

AngleAxis

用法非常類似上述對rotation賦值,其本質是 函數創建並返回一個四元數,進行賦值

//Quaternion AngleAxis(float angle, Vector3 axis):繞 axis軸,旋轉 angle 度
objsTrans[1].rotation = Quaternion.AngleAxis(90, Vector3.forward);

SetLookRotation()

功能類似Transform.LookAt(),但注意,此處View參數不是目標物體的坐標,而應是兩者的矢量差(當前物體指向目標物體的矢量)。up含義同上文所提的worldUp。

// SetLookRotation(Vector3 view);  
// SetLookRotation(Vector3 view, Vector3 up= Vector3.up);  
Quaternion quaternion = Quaternion.identity;
quaternion.SetLookRotation(objsTrans[2].position-objsTrans[1].position);
objsTrans[1].rotation = quaternion;	//使物體1看向物體2

LookRotation()

用法及含義同SetLookRotation()

// LookRotation (Vector3 forward, Vector3 upwards= Vector3.up);
Quaternion quaternion = Quaternion.LookRotation((objsTrans[2].position - objsTrans[1].position), Vector3.up);
objsTrans[1].rotation = quaternion;

SetFromRotation()

直觀理解:存在物體123,物體1以自身為中心,由12的向量旋轉為13的向量;就像三物體處於扇形的三個端點,物體1旋轉的度數為該扇形的圓心角。注意區別於LookAt()LookAt()方法是z軸始終指向目標物體,而該方法是12、13物體間的虛擬連線的方向變更,不涉及z軸朝向誰。

// SetFromToRotation (Vector3 fromDirection, Vector3 toDirection):創建一個從 fromDirection 旋轉到 toDirection 的旋轉
Quaternion quaternion = new Quaternion();
quaternion.SetFromToRotation(objsTrans[2].position, objsTrans[3].position);	//設定初始和最終朝向坐標
objsTrans[1].rotation = quaternion;

Slerp()

直觀理解:物體1從物體2的rotation、進行插值旋轉變為物體3的rotation。

// Quaternion Slerp(Quaternion a, Quaternion b, float t):在 a 和 b 之間以球形方式插入 t。參數 t 被限制在 [0, 1] 範圍內
objsTrans[1].rotation = Quaternion.Slerp(objsTrans[2].rotation, objsTrans[3].rotation, Time.time);

參考

Tags: