Unity開發中常用的基礎3D數學(向量,點乘,叉乘,矩陣,四元數,尤拉角)
在看了很多文章和書籍直後發現Unity中的數學知識是很重要的,想要做到遊戲的高真實度和高流暢度,數學是必不可少的,今天就來記錄一下基礎的3D數學在Unity中開發時的運用,若文章中所寫有不足,歡迎指出留言,互相交流,感謝!
轉載請標註轉載地址
一、Unity中的向量
向量這個詞大家應該不陌生,在數學裡向量就是一個方向,沒有大小,同樣,在Unity中我們可以根據向量去獲取方向。比如說,我想把a物體移動到b物體所在的位置,那麼首先我們要做的就是先確定我們前進的方向,在確立了方向之後,就可以按照我們想要的速度向b目標點移動了,Unity中使用向量的加法來實現物體位移,程式碼如下:
/// <summary>
/// 向量的加法(從a位置移動到b位置)
/// </summary>
public void Add()
{
//先計算二者方向
Vector3 dir = (target.position - cube.position).normalized;
//開始從a位置移動到b位置
cube.position = cube.position + dir * Time.deltaTime * 3;
}
其中,(target.forward - cube.forward)可以求得一個向量值,此處可以將該向量理解為有方向有大小的向量,normalized表示該向量長度為1,向量沒有大小,所以如果光是向量的話並不能完全表示朝向,將其大小設定為noemalized可以很好的表示出向量的朝向。
Unity中對於向量最好的一個例子是Vector3.Distance(),這個方法很常用,用來求得兩個物體之間的距離,或者作為攻擊範圍等來使用,其實它的原理就是用兩個向量相減求平方根得到的距離值,程式碼如下:
/// <summary>
/// 向量的減法(計算a,b兩物體間的距離)
/// </summary>
public void Sub()
{
float dic = Vector3.Distance(cube.position, target.position);
print("距離為:" + dic);
}
二、向量的點乘和叉乘
很多地方出現過這麼一句話:向量的點乘(Dot)判斷角度,向量的叉乘(Cross)判斷方向
先說點乘,點乘在Unity中的使用是用來計算兩個物體之間角度,用Vector2.Dot()或Vector3.Dot()方法可以得到一個弧度制,也就是這兩個物體夾角的弧度值,可以使用Mathf.Acos(弧度制)*Rad2Deg來轉換為夾角的角度值。對於點乘的理解2D的理解起來比較簡單,數學中的勾股定理,當知道斜邊長度為a,一條直角邊長度為b,夾角為R,那麼b = a*cosR,如下圖所示:
叉乘判斷方向,叉乘是兩物體的法向量,舉個例子,當我們的主角沒有面對怪物時,我們可以先用點乘計算出當前主角的朝向和怪物當前朝向的角度,然後用叉乘我們可以判斷出怪物是在我們的前?後?左?右?根據右手定則,當指向我們自己時,四指是逆時針,指向我們面朝方向時四指是順時針,無論當前指向哪裡,超過180度時都會變換朝向,所以叉乘時時刻刻都會告訴我們怎麼轉是最近的,Unity中我們用Vector3.Cross()計算兩物體的叉乘,返回值是一個Vector3型別,最大為1最小為-1。我們可以用一個案例來理解點乘和叉乘:
public class SteeringWheelScript : MonoBehaviour {
private GameObject image;
private Vector3 imageTra;
//滑鼠點向量
Vector3 mouseVec;
//上一幀滑鼠點向量
Vector3 beforeMouseVec;
//滑鼠點上一幀位置
Vector3 beforeMousePos;
private void Awake()
{
image = GameObject.Find("Canvas/Image");
imageTra = image.transform.position;
//beforeMousePos = imageTra;
}
/// <summary>
/// 得到滑鼠座標
/// </summary>
/// <returns>返回當前滑鼠位置</returns>
public Vector3 GetMousePos()
{
if (EventSystem.current.IsPointerOverGameObject()&&Input.GetMouseButton(0)&&!Input.GetMouseButtonUp(0))
{
return Input.mousePosition;
}
else
return default(Vector3);
}
/// <summary>
/// 開始轉動
/// </summary>
public void TurnRun(Vector3 currentMousePos)
{
//得到向量
mouseVec = (currentMousePos - imageTra).normalized;
beforeMouseVec = (beforeMousePos - imageTra).normalized;
//計算方向
Vector3 direction = Vector3.Cross(beforeMousePos.normalized, beforeMouseVec.normalized);
print("方向:" + direction.z);
//計算角度
float radianValue = Vector3.Dot(beforeMouseVec.normalized, currentMousePos.normalized);//得到弧度值
float angleValue = Mathf.Acos(radianValue) * Mathf.Rad2Deg;//角度
print("角度:" + angleValue);
//順時針轉
if (direction.z > 0)
{
image.transform.eulerAngles = new Vector3(0,0, angleValue);
}
//逆時針
else if (direction.z < 0)
{
image.transform.eulerAngles = new Vector3(0, 0, -angleValue);
}
beforeMousePos = currentMousePos;
}
private void FixedUpdate()
{
TurnRun(GetMousePos());
}
}
這個是模擬方向盤的轉動,這裡我用的是UGUI,Unity版本是5.6,EventSystem.current.IsPointerOverGameObject()是用來判斷當前滑鼠是否在UI上面。
三、矩陣
矩陣在3D引擎底層實現中使用的非常多,對於矩陣,我們從固定流水線開始理解,固定流水線是指一個3D物體在顯示器上成像的過程,在這個過程中就用到了非常多的矩陣轉換。用一個比較好理解的方式來說吧,首先,當我們需要一個3D模型時,會讓美工開始在3DMax裡面製作,製作完成匯出FBX格式,當前這個模型就是一個個體,也就是區域性座標,然後我們會把模型匯入Unity中調整位置,進行拖拽,這個過程使得模型從單個個體變為了Unity中模型的其中之一,也就是世界座標,此時我們要看到該模型,所以新增攝像機,把模型放在攝像機視野內,這樣,又從世界座標變成了觀察座標,當然,攝像機看不到的模型背面就會被優化掉,那麼觀察座標就變成了裁剪座標,之後為了把模型顯示在螢幕上,又把裁剪座標變為視口座標,最後進行光柵化完成固定流水線。
以上是對矩陣的一個簡單瞭解,物體的縮放,旋轉,位移,雖然我們直接用Rotate等函式就可以很便捷的完成,但是其底層實現也是矩陣的變換,這裡說一個小點,3D空間中,點是三維的,而矩陣是四維,這裡涉及到了齊次座標,進行矩陣計算時,會把三維的點轉變成齊次座標然後才可以計算,因為像位移,旋轉,縮放等三維矩陣是完成不了的,點轉為齊次座標時會用1補齊第四位比如(x,y,z,1)
四、四元數
四元數在Unity中主要用於做旋轉使用,這裡說幾個很常用的四元數方法,Quaternion.Eular()可以獲取物體的四元數,Rotation就是一個四元數,但是不可以直接對它進行賦值,這裡可以用到eularAngle 進行賦值,控制物體的旋轉可以用AngleAxis()方法進行操作。
五、尤拉角
使用尤拉角進行旋轉賦值時一定可能性會出現萬向節死鎖,什麼是萬向節死鎖,其實萬向節死鎖的原因是尤拉角本身,尤拉角旋轉賦值一般情況下是一對一,比如,旋轉X軸,旋轉Y軸,旋轉Z軸,但是在一些情況下會變成一對多,比如旋轉Z軸,X軸和Z軸進行了旋轉使得整體旋轉發生改變,X軸的旋轉自由缺失,這種情況最好的避免方式是,僅對一個軸進行賦值,其餘軸為0。直接使用尤拉角的程式碼效率還是比較高的。
到此Unity中比較常用的基礎3D數學也就介紹完了,整體我是沿著在Unity開發中的使用來介紹的,如果大家對其中某些部分有興趣可以去查閱一下資料,深挖一下。
相關文章
- 旋轉的數學表達:尤拉角、軸向角、四元數與矩陣矩陣
- 【數學】向量點乘、叉乘的理論、應用及程式碼實現(C++)點乘C++
- 向量點乘為降維,叉乘為升維點乘
- 3D數學基礎:矩陣的行列式3D矩陣
- 旋轉矩陣與尤拉角的相互轉換矩陣
- 尤拉角和旋轉矩陣之間的轉換矩陣
- 人工智慧數學基礎—-矩陣人工智慧矩陣
- 人工智慧數學基礎----矩陣人工智慧矩陣
- 【矩陣求導】關於點乘 (哈達瑪積)的矩陣求導矩陣求導點乘
- three.js 尤拉角和四元數JS
- 三維旋轉矩陣 左乘和右乘分析矩陣
- 基礎|什麼是張量、資料立體、矩陣、向量和純數矩陣
- 三維空間變換中旋轉矩陣左乘與右乘的區別矩陣
- C語言:將一個4X4的矩陣賦值,矩陣元素的值為其行數與列數的乘積C語言矩陣賦值
- 機器學習中的矩陣向量求導(五) 矩陣對矩陣的求導機器學習矩陣求導
- 尤拉計劃621:把整數表示為三角數之和
- 基向量 變換矩陣矩陣
- NYOJ 1409 快速計算【矩陣連乘】矩陣
- 卷積運算元的矩陣向量乘積表示&一維離散降質模型卷積矩陣模型
- 機器學習中的矩陣向量求導(四) 矩陣向量求導鏈式法則機器學習矩陣求導
- 社交網路分析的 R 基礎:(三)向量、矩陣與列表矩陣
- 矩陣類及其常規運算(加、減、乘、轉置、求逆、行列式、代數餘子式、伴隨矩陣)矩陣
- 尤拉計劃725:數位之和數
- 矩陣連乘(動態規劃演算法)矩陣動態規劃演算法
- 矩陣連乘問題 Python 動態規劃矩陣Python動態規劃
- 尤拉計劃714:兩種數位的數
- 尤拉計劃704:二項式係數中的2因數
- 尤拉計劃698:123數
- 尤拉計劃719:拆分數
- 素數個數 <埃式篩 && 尤拉篩>
- Note -「因數的尤拉函式求和」函式
- 求任意數字的階乘
- 大規模 Transformer 模型 8 位元矩陣乘簡介ORM模型矩陣
- OpenGL/OpenGL ES 入門:基礎變換 - 初識向量/矩陣矩陣
- 淺析拉格朗日乘數法及其對偶問題
- 從尤拉捐贈中,讀懂數字基建與數字中國
- 尤拉計劃699:三腳數
- 尤拉計劃706:三象數