C#程式設計師整理的Unity 3D筆記(十):Unity3D的位移、旋轉的3D數學模型
遇到一個想做的功能,但是實現不了,核心原因是因為對U3D的3D數學概念沒有靈活吃透。故再次系統學習之—第三次學習3D數學.
本次,希望實現的功能很簡單:
如在小地圖中,希望可以動態畫出Player當前的位置、z的朝向:用3條線、z軸正向、30°旋轉、-30°旋轉。
問題是:0點可以獲得,P1點? P2點是未知的。
我嘗試了2個小時,結果不竟如人意,少於沮喪。
不得不,再次花點時間系統的學習3D數學:
1 位移–向量和點:
點: 點和向量在數學上是一致的,實際生活中點的概念比較好理解,座標點來定位–南二環、北二環。 【點用(3,4,5)圓括號來標示,簡稱P】
向量:“俗稱增量”,有大小和方向,如”往前1步走。 左轉90度”. 往前走,直到碰到牆,你才會停下來—在這之前,你無法準確獲得碰到牆的點的座標或者你和牆的距離。
在U3D中,統一用Vector3物件來表達向量和點,這個也是導致新手暈頭轉向的一個很重要的原因; 一個技巧,凡是在API中用position、Point的,V3肯定代表是點;凡是Vector、direction的是向量;多看官方的API手冊,寫得很明白。
做個遊戲,列表出你用過的Vector3的API,分析分析用到的Vector3是向量(V)還是點(P)
需求 |
API |
向量(V) 點(P) |
備註 |
平滑位移 |
Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta); |
P |
|
平滑位移 |
Vector3 Slerp(Vector3 from, Vector3 to, float t) |
P |
|
新的座標點 |
this.m_transform.position = pos; |
P |
符合常規思維 |
變動一次座標 |
m_transform.Translate(new Vector3(rx, 0, -m_Speed * Time.deltaTime)); |
V |
可認為是增量 |
求方向 |
Vector3 relativePos = this.m_transform.position – m_Player.position; |
V |
向量減法,較難理解 |
設定新座標點 |
lineRenderer.SetPosition(0,this.gameObject.transform.position); m_NavAgent.SetDestination(this.m_Player.transform.position); |
P |
符合常規思維 |
新的位置 |
pointer.transform.position = hitInfo.point + (transform.position – hitInfo.point) * 0.01f; |
P、V |
力的疊加? |
求距離 |
float dis = Vector3.Distance(v1, v2); float f1 = (v1 – v2).sqrMagnitude; float f3 = (v1 – v2).magnitude; |
P、V |
Distance用點即可 向量減法也可以 |
縮放正向 |
Vector3 v3 = this.m_transform.forward * 200f; |
V |
V的數乘 |
射線檢測 |
Ray r = new Ray(source, dest); Physics.Raycast(r, out hit, 1000, m_ShootMask) |
V、P |
Source:P Dest:V |
加一個力 |
rigidbody.AddForce (0, 10, 0); |
V |
依據這個遊戲,可以整理出目前用到的有4個元件(含Vector 3)會發生位移:
位移常用的4個元件和Vector3:
元件 |
函式 |
Unity 聖典的API說明 |
是否 用過 |
transform元件 |
translate函式 |
向某方向移動物體多少距離【預設local座標系】 或者相對某物體移動 |
yes |
Position屬性 |
在世界空間座標transform的位置 |
Yes |
|
RigidBody元件 [FixedUpdate函式] |
Velocity屬性 |
剛體的速度向量 Unity 官方demo Done用的很酷 |
Yes |
AddForce函式 |
新增一個力到剛體。作為結果剛體將開始移動。 |
yes |
|
MovePosition函式 |
移動剛體到position |
||
NavMeshAgent元件 |
SetDestination函式 |
設定自動Path目標點 |
yes |
CharacterController 元件 |
Move函式 |
一個更加複雜的運動函式,每次都絕對運動 |
yes |
SimpleMove函式 |
以一定的速度移動角色 |
||
Vector3向量 |
Lerp函式 |
兩個向量之間的線性插值。 “像彈簧一個跟隨目標物體” |
|
Slerp函式 |
球形插值在兩個向量之間 “在日出和日落之間動畫弧線” |
||
MoveToward函式 |
當前的地點移向目標 和Vector3.Lerp相同,maxDistanceDelta限速 |
||
SmoothDamp 函式 |
隨著時間的推移,逐漸改變一個向量朝向預期的目標。 |
我的幾個向量相關的問題:
如何判斷A向量和B向量是否同方向?
如何判斷A向量和B向量前、後、左、右?
如何判斷A向量和B向量的夾角?
向量的減法貌似比加法更有用一些?
Vector.Forward和this.transform.Forward都表達local座標系,那麼數值為什麼不一樣呢?
2 旋轉–Quaternion、eulerAngles、Quaternion.Euler
旋轉在3D中是比較複雜的,在Unity 3D中一般用Quaternion來進行旋轉, 旋轉僅涉及向量的概念(向量的方向),請思考對於座標點或者零向量旋轉有無意義?
而按照Unity 3D API官方的說法,僅有約7個方法或者操作符比較常用,且佔99%的概率,我截止目前還沒有用到這麼多,我用到的Quaterniong約有4個函式。
旋轉常用7個API:
Quaternion API |
Unity 聖典的API說明 |
是否 用過 |
Quaternion.LookRotation |
建立一個旋轉,沿著forward(z軸)並且頭部沿著upwards(y軸)的約束注視。也就是建立一個旋轉,使z軸朝向y軸朝向up。 常用的是transform.LookAt |
yes |
Quaternion.Angle |
返回a和b兩者之間的角度。 |
|
Quaternion.Euler |
返回一個旋轉角度,繞z軸旋轉z度,繞x軸旋轉x度,繞y軸旋轉y度(像這樣的順序)。 |
yes |
Quaternion.Slerp |
球形插值,通過t值from向to之間插值。 |
|
Quaternion.FromToRotation |
從fromDirection到toDirection建立一個旋轉。 |
|
Quaternion.identity |
返回恆等式旋轉(只讀)。這個四元數對於“無旋轉”:這個物體完全對齊於世界或父軸。 |
yes |
Quaternion.operator * |
由另一個四元數來旋轉一個旋轉角度,或由一個旋轉角度來旋轉一個向量 |
yes |
我的幾個旋轉相關的問題:
1 Quaternion.LookRotation和Vector3.RotateTowards的區別?
2 Quaternion.Angle和Vector3.Angle的區別?
3 Quaternion.LookRotation和transform.LookAt的區別?
[官方回答: 大多數時間你可以使用transform.LookAt代替
Quaternion.LookRotation]
4 如何實現2個GameObject face to face,即Z軸相對?
磨刀不誤砍柴工: 經過一週的複習、反覆驗證,果然在系統學習3D 數學後,要實現的功能可以了,如下:
參考部落格:
座標系的簡介:C#程式設計師整理的Unity 3D筆記(八):Unity 3D座標系介紹
宣雨鬆的部落格:http://www.xuanyusong.com/archives/1977
總結:
據說80%、90%Unity 3D程式設計師是自學的,大多數是看看書、實戰視訊、原始碼分析;而科班出生的同學會有3D數學這門核心課–估計佔一個學期、會有作業等。為了趕上科班同學的水平,花點時間,補補數學知識,會使得自己少走一些彎路。一句話:”3D數學模型很關鍵。“
轉載於:https://my.oschina.net/xifarm/blog/372497