學了那麼久 其實對Unity的歐拉角和四元數并沒有很深刻的認識…是以就此開篇稍微介紹一下
- 我們首先知道的是,在Unity中有兩種方式表示旋轉。一種是歐拉角,還有一種就是四元數,那其中的差別有哪些呢?我們先分别介紹一下。
一.歐拉角
歐拉角最容易表示,用三個變量X,Y,Z可以直覺的表示繞着某個軸的旋轉角度。
在Unity裡就是Transform元件的Rotation裡的X Y Z三個變量代表了歐拉角
二.四元數
四元數相比于歐拉角就比較複雜了,由四個變量組成(在Unity中稱為X,Y,Z,W),但是這些變量的值不代表旋轉角度,是以可能給你一個向量(0。7,0,0,0.7)你并不知道實際旋轉的角度,當然四元數的詳細解釋需要數學方面的深入研究,有興趣的可以自行查找有關資料
- 因為在Unity沒有可視化界面可以調整四元數(因為真的調了也不直覺看到旋轉的角度),是以我們隻能用腳本來通路
三.腳本中内容
歐拉角如果在腳本中表示呢?
是不是想到之前圖中的那個Rotation,那你是不是自然而然的想到了通過transform.rotation通路呢?如果你是這樣想的,那就錯了!
在Unity中transform.rotation代表的是四元數!附上官網證明!
那到底如何表示歐拉角呢?其實表示很簡單,并附上官網解釋
transform.eulerAngles =new Vector3(20,300,40);
當我們以上述代碼運作後會發現Rotation中的Y值是-60,那是因為面闆上的Rotation中的X Y Z值範圍是在(-180,180),對于代碼中超出的部分會自動進行計算映射到範圍内
四元數的代碼表示就是之前的transform.rotation,那你肯定會想歐拉角和四元數之前能否轉換呢,知道其中一個的值,如果改變成對方呢?代碼如下
//歐拉角->四元數
//通過Quaternion.Euler() 傳遞一個Vector3向量的歐拉角
transform.rotation = Quaternion.Euler(new Vector3(20, 300, 40));
//四元數->歐拉角
transform.rotation.eulerAngles;//對你沒看錯 直接可以轉換擷取
三.差別
歐拉角:
- 優點:三個角度組成,直覺,容易了解
- 優點:可以進行從一個方向到另一個方向旋轉大于180度的角度
- 缺點:死鎖問題——萬向節死鎖 萬向節死鎖介紹
四元數
- 優點:不存在萬向節死鎖問題
- 優點:存儲空間小,計算效率高
- 缺點:單個四元數不能表示在任何方向上超過180度的旋轉。
- 缺點:數字表示不直覺
四.常用API
- Quaternion.LookRotation() 使其轉向某個方向 函數傳遞的參數的一個Vector3的向量 這個向量表示的是要看向的向量,通常用目标的positon和自身的position進行相減求得此向量
Vector3 pos = target.transform.position - transform.position;
transform.rotation = Quaternion.LookRotation(pos);
是不是覺得和transform.LookAt()效果很像…
//和上面代碼得到的效果相同
transform.LookAt(target.transform);
- Quaternion.Slerp() 平滑進行轉動動畫
函數傳遞的參數分别是 目前GameObject的四元數、目标要轉向的四元數 和 一個插值時間
我們看個例子
void LookAtTarget()
{
if (Input.GetKey(KeyCode.Space))
{
Vector3 dir = target.transform.position - transform.position;
dir.y = 0;//不讓Player有y軸上的傾角
Quaternion target = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime);
}
}
我們将上述的LookAtTarget()方法放到Update()函數中進行執行
就可以看到平滑的轉動
- Quaternion.Lerp() 說實話個人用起來和Slerp()差別不大 圖中紅線框出來的就是差別:使用Lerp()進行旋轉的速度較快,但是在旋轉角度較大的時候,效果會糟一點。
- Quaternion.RotateTowards() 傳遞兩個四元數,和一個角度增量值,使第一個四元數逐漸趨近于第二個四元數并最終相等
void Update()
{
float step = 3 * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation,target.transform.rotation,step);
}
結果就是目前物體的四元數和目标的四元數相等
- Transform.RotateAround() 傳遞一個參照點point、繞哪個軸轉axis和增量角度angle
void Update()
{
float step = 3 * Time.deltaTime;
transform.RotateAround(target.transform.position,Vector3.up,step);
}
五.總結
差不多基礎概念就這些了吧,如果要深入了解的話,建議還是看API,并且自己多動手嘗試一下資料~