歐拉角
三個數字來保存方位,共用vector3,但此時它不代表向量。
優點
•僅使用三個數字表達方位,佔用空間小。
•沿座標軸旋轉的單位爲角度,符合人的思考方式。
•任意三個數字都是合法的,不存在不合法的歐拉角。
//歐拉角,每次疊加(1,0,0)旋轉
transform.eulerAngles+=transform.right;
//與前者等效,但實際涵義不同,內部使用的四元數
transform.Rotate(transform.right);
缺點:
對於一個方位,存在多個歐拉角描述,因此無法判斷多個歐 拉角代表的角位移是否相同。
例如角度250,0,0與角度290,180,180是同一個歐拉角,難以直觀判斷。
爲了保證任意方位都只有獨一無二的表示,Unity引擎限制 了角度範圍,即沿X軸旋轉限制在-90到90之間,沿Y與Z軸 旋轉限制在0到360之間。
歐拉角會造成萬向節死鎖。
四元數
因爲歐拉角的缺點,數學家提出了四元數。
缺點:
難於使用,不建議單獨修改某個數值。
•存在不合法的四元數。
兩個四元數相乘可以組合旋轉效果,四元數不能使用+號,表示疊加關係是*號
//物體沿自身y軸旋轉1°
transform.rotation *= Quaternion.Euler(0,1,0);
//下面兩行等價
//Quaternion.Euler(0, 30, 0) *Quaternion.Euler(0, 20, 0)
//Quaternion.Euler(0, 50, 0);
四元數左乘向量,表示將該向量按照四元數表示的角度旋轉:
Vector3 point = new Vector3(0,0,10);
Vector3 newPoint= Quaternion.Euler(0,30,0) * point ;
所以已知一個向量,已知旋轉角度,就能求得新向量。
比起三角函數求向量,更爲簡單!
練習:
//新向量爲 當前物體的位置對應的正前方10米,偏轉30°
Vector3 newpoint= transform.position+ Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);
練習:求兩個物體之間的切線:
腳本綁定在球體上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class aaa : MonoBehaviour
{
public Transform cube;
// Update is called once per frame
void Update ()
{
Vector3 sub = transform.position - cube.position;
float c = sub.magnitude;
//算出夾角,球體半徑0.5f
float angle = Mathf.Asin(0.5f / c) * Mathf.Rad2Deg;
//要加上cube.position,因爲需要平移
Vector3 leftpoint =cube.position+ Quaternion.Euler(0, angle, 0) * sub;
Vector3 rightpoint = cube.position + Quaternion.Euler(0, -angle, 0) * sub;
Debug.DrawLine(cube.position, leftpoint);
Debug.DrawLine(cube.position, rightpoint);
}
}
個人實踐
正因爲四元數和歐拉角各有優缺點,所以unity提供了Rotate函數,它的參數是歐拉角,提供了方便,但內部使用四元數,又避免了歐拉角的缺點。
歐拉角與四元數也廣泛使用在unity開發中。
處了前面的那些,Quaternion結構還提供了不少常用的函數:
比如 Quaternion.AngleAxis,作用與 Quaternion.Euler相似;
Quaternion.LookRotation,作用與transform.LookAt相似;
Quaternion.RotateTowards,勻速旋轉,類比結構vector3中的vector3.MoveTowards 勻速移動。
Quaternion.Lerp,變速旋轉,類比結構vector3中的vector3.Lerp 變速移動。
個人實踐經驗,可以通過向量來理解四元數的旋轉,但必須記住,四元數是一種角度,而不是向量。
Quaternion.LookRotation其含義是把z軸藍色旋轉到某個向量方向需要的角度。
如果unity沒有提供LookRotation,完全可以自己實現—需要先算出兩個向量的夾角,再根據夾角旋轉。
簡單用向量理解,把藍色z軸向量旋轉到某個向量方向。
void Update ()
{
if (Input.GetButtonDown("Jump"))
{
transform.rotation = Quaternion.LookRotation(cube.position - transform.position);
}
}
Quaternion.FromToRotation的含義:把某個軸旋轉到某個向量方向需要的角度。
transform.rotation= Quaternion.FromToRotation(transform.forward, cube.position-transform.position);
此時的Quaternion.FromToRotation和Quaternion.LookRotation等價。
當我需要把紅軸旋轉到某個向量方向時:
transform.rotation= Quaternion.FromToRotation(transform.right, cube.position-transform.position);
假設想讓物體慢慢旋轉,可以旋轉勻速旋轉:
//需要的角度
Quaternion targ = Quaternion.LookRotation(cube.position - transform.position);
//當前物體角度,需要的角度,每次的增量歐拉角1°
transform.rotation= Quaternion.RotateTowards(transform.rotation, targ, 1);
Quaternion.Angle 也可以算出角度,簡易理解爲兩個物體的藍色軸或紅色軸之間的夾角。
angle = Quaternion.Angle(transform.rotation, cube.rotation);
到目前爲止我學了算角度:
① 向量之間的三角函數
②向量的dot 點乘
③vector3.angle, 點乘的簡化形式
④Quaternion.Angle,旋轉後軸之間的夾角。