1. 程式人生 > 實用技巧 >C#程式設計師整理的Unity 3D筆記(十):Unity3D的位移、旋轉的3D數學模型

C#程式設計師整理的Unity 3D筆記(十):Unity3D的位移、旋轉的3D數學模型

遇到一個想做的功能,但是實現不了,核心原因是因為對U3D的3D數學概念沒有靈活吃透。故再次系統學習之—第三次學習3D數學.

本次,希望實現的功能很簡單:

image

如在小地圖中,希望可以動態畫出Player當前的位置、z的朝向:用3條線、z軸正向、30°旋轉、-30°旋轉。

問題是:0點可以獲得,P1點? P2點是未知的。

我嘗試了2個小時,結果不竟如人意,少於沮喪。

image

不得不,再次花點時間系統的學習3D數學:

1 位移–向量和點:

  • 點: 點和向量在數學上是一致的,實際生活中點的概念比較好理解,座標點來定位–南二環、北二環。 【點用(3,4,5)圓括號來標示,簡稱P】

  • 向量:“俗稱增量”,有大小和方向,如”往前1步走。 左轉90度”. 往前走,直到碰到牆,你才會停下來—在這之前,你無法準確獲得碰到牆的點的座標或者你和牆的距離

    【向量用<3,4,5>尖括號來標示,簡稱V】

  • 在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 數學後,要實現的功能可以了,如下:

image

參考部落格:

座標系的簡介:C#程式設計師整理的Unity 3D筆記(八):Unity 3D座標系介紹

宣雨鬆的部落格:http://www.xuanyusong.com/archives/1977

總結:

據說80%、90%Unity 3D程式設計師是自學的,大多數是看看書、實戰視訊、原始碼分析;而科班出生的同學會有3D數學這門核心課–估計佔一個學期、會有作業等。為了趕上科班同學的水平,花點時間,補補數學知識,會使得自己少走一些彎路。一句話:”3D數學模型很關鍵。“

轉載於:https://my.oschina.net/xifarm/blog/372497