理論部分
1. 概念
- 向量(vector):既有大小(magnitude )又有方向(direction)的量叫做向量梁棠。向量是物理惨缆、動畫、三維圖形的基礎(chǔ)嵌洼。
- 標量(scalar):只有大小沒有方向的量赖捌。例如物體移動中的平均速率祝沸、路程。
- magnitude : 向量的長度
- 模:向量的長度標準化(Normalizing)越庇,即保持方向不變罩锐,將向量的長度變?yōu)?。
Although vector operations are easy to describe, they are surprisingly subtle and powerful and have many uses in games programming. Vector arithmetic is fundamental to 3D graphics, physics and animation and it is useful to understand it in depth to get the most out of Unity
-
如果我們定義一個vector3(2.5,2)卤唉,這意味這什么呢涩惑?在Unity中,所有的向量都是從世界坐標零點開始桑驱。因此這個向量表示從vector.zero發(fā)出的一條線竭恬,到(2,5熬的,2)這個地方停止痊硕。由于這條直線都是從vector.zero發(fā)出,因此我們可以把它看成是一個三維世界中的點押框。
2. 向量運算
-
向量加法:
如果我們把第一個vector看作是一個點岔绸,那相加的結(jié)果就是從第一個點開始,“跳躍”另一個加數(shù)后的結(jié)果。比如上面的圖中盒揉,C可以看作是a向右跳了2晋被,又向下跳了1的結(jié)果。如果我們想計算一個物體離地面的距離刚盈,我們可以這樣寫:
var pointInAir = pointOnGround + new Vector3(0, 5, 0);
-
向量減法:
向量減法常用于取得一個對象到另一個對象之間的方向和距離墨微。注意減法式子中的參數(shù)順序會影響到結(jié)果。
- 標量乘/除(scalar):
- Multiplying a vector by a scalar results in a vector that points in the same direction as the original. However, the new vector’s magnitude is equal to the original magnitude multiplied by the scalar value.
- Likewise, scalar division divides the original vector’s magnitude by the scalar.
- When any vector is divided by its own magnitude, the result is a vector with a magnitude of 1, which is known as a normalized vector.(標準化向量)扁掸。If a normalized vector is multiplied by a scalar then the magnitude of the result will be equal to that scalar value. This is useful when the direction of a force is constant but the strength is controllable (eg, the force from a car’s wheel always pushes forwards but the power is controlled by the driver).
- scalar的結(jié)果始終是:方向不變,長度(magnitude)改變最域;當一個向量被自身的magnitude除以后谴分,始終得到magnitude=1的向量,這就叫做向量的標準化(Normalizing)模镀脂。標準化后的向量再次scalar后牺蹄,這個向量的magnitude就等于scalar。
- 點乘(Dot Product):
點乘就是兩個向量相乘薄翅,點乘的結(jié)果始終是一個標量(scalar)沙兰;等于兩個vector的長度相乘再乘以兩個向量夾角的余弦。
如果兩個向量都是標準化向量翘魄,那么a·b等于向量b在向量a方向上的投影的長度(或者說向量a在向量b方向上的投影)鼎天。,兩個向量的前后次序并不重要
點乘可以用來方便的判斷兩個向量是否彼此垂直暑竟,點乘結(jié)果為0時兩者垂直
The dot product is a very simple operation that can be used in place of the Mathf.Cos function or the vector magnitude operation in some circumstances (it doesn’t do exactly the same thing but sometimes the effect is equivalent). However, calculating the dot product function takes much less CPU time and so it can be a valuable optimization.
點乘運算可以極大的節(jié)省CPU資源斋射。
-
叉乘(Cross Product)a ^ b:
-
只適用于三維空間,計算兩個向量但荤,返回一個新的向量罗岖。新向量的方向和前兩個向量垂直。
-
叉乘的運算公式:向量a和b的長度相乘腹躁,再乘以它們夾角的正弦值
-
一個顯而易見的用途就是叉乘可以用來計算法線
3. 兩個物體之間的距離和方向
兩個向量a,b相減(a-b)的結(jié)果是得到一個新向量桑包,從b指向a;反之亦然
var heading = target.position - player.position; // 1
1.得到player指向target的向量
var distance = heading.magnitude;// 2
var direction = heading / distance; // 3
- 得到這個向量的長度
- 所以纺非,player向著目標點的方向就是長度/距離(Normalized magnitude)
我們這樣計算的目的是為了同時獲得新向量的長度和標準化后的向量以便于下一步計算哑了。這兩個數(shù)值的計算都是cpu heavy的。因為他們的計算都需要開平方铐炫。
if (heading.sqrMagnitude < maxRange * maxRange) {
// Target is within range.
}
- 有時我們只想知道方向垒手,而不想知道player距離target有多遠,為了避免計算magnitude倒信,我們可以使用
sqrMagnitude
方法計算magnitude的平方科贬,這樣可以避免開方運算,節(jié)省cpu資源。This is much more efficient than using the true magnitude in the comparison.
4. 計算垂直vector
當給定空間中的3個點后榜掌,我們只需要從任意一個點出發(fā)优妙,得到它到另外兩個點的向量,然后對這兩個向量做叉乘即可:
var a: Vector3;
var b: Vector3;
var c: Vector3;
var side1: Vector3 = b - a;
var side2: Vector3 = c - a;
var perp: Vector3 = Vector3.Cross(side1, side2);
那么這個新向量的長度是多少呢憎账?它應該等于三角形的面積×2
5.使用點乘
想象一輛車的碼表套硼,其速度計算依賴于車輪胎前進的方向,但是車子在某些情況下也有側(cè)滑等情況出現(xiàn)胞皱,這時邪意,碼表計算時就應該把側(cè)滑的速度也計算進去。我們可以通過rigidbody.velocist
得到車子總體的位移情況反砌,但為了將其投影到前向雾鬼,我們可以使用點乘:
var fwdSpeed = Vector3.Dot(rigidbody.velocity, transform.forward);
【參考文獻】