Unity中的向量(vector)

理论部分

1. 概念

  • 向量(vector):既有大小(magnitude )又有方向(direction)的量叫做向量。向量是物理、动画、三维图形的基础。
  • 标量(scalar):只有大小没有方向的量。例如物体移动中的平均速率、路程。
  • magnitude : 向量的长度
  • 模:向量的长度标准化(Normalizing),即保持方向不变,将向量的长度变为1。

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发出的一条线,到(2,5,2)这个地方停止。由于这条直线都是从vector.zero发出,因此我们可以把它看成是一个三维世界中的点。
    magnitude计算:Vector3.magnitude

2. 向量运算

  • 向量加法:


    When two vectors are added together, the result is equivalent to taking the original vectors as “steps”, one after the other. Note that the order of the two parameters doesn’t matter, since the result is the same either way.

    如果我们把第一个vector看作是一个点,那相加的结果就是从第一个点开始,“跳跃”另一个加数后的结果。比如上面的图中,C可以看作是a向右跳了2,又向下跳了1的结果。如果我们想计算一个物体离地面的距离,我们可以这样写:

var pointInAir = pointOnGround + new Vector3(0, 5, 0);
  • 向量减法:


    Vector subtraction is most often used to get the direction and distance from one object to another. Note that the order of the two parameters does matter with subtraction:-

    向量减法常用于取得一个对象到另一个对象之间的方向和距离。注意减法式子中的参数顺序会影响到结果。


    image.png
  • 标量乘/除(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的结果始终是:方向不变,长度(magnitude)改变;当一个向量被自身的magnitude除以后,始终得到magnitude=1的向量,这就叫做向量的标准化(Normalizing)模。标准化后的向量再次scalar后,这个向量的magnitude就等于scalar。
  • 点乘(Dot Product):
    The dot product takes two vectors and returns a scalar. This scalar is equal to the magnitudes of the two vectors multiplied together and the result multiplied by the cosine of the angle between the vectors.

    点乘就是两个向量相乘,点乘的结果始终是一个标量(scalar);等于两个vector的长度相乘再乘以两个向量夹角的余弦。
    如果两个向量都是标准化向量,那么a·b等于向量b在向量a方向上的投影的长度(或者说向量a在向量b方向上的投影)。,两个向量的前后次序并不重要
常见角度的余弦值

点乘可以用来方便的判断两个向量是否彼此垂直,点乘结果为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.
点乘运算可以极大的节省CPU资源。

  • 叉乘(Cross Product)a ^ b:

    • 只适用于三维空间,计算两个向量,返回一个新的向量。新向量的方向和前两个向量垂直。


      左手定理
    • 叉乘的运算公式:向量a和b的长度相乘,再乘以它们夹角的正弦值


      image.png

      叉乘的表示
  • 一个显而易见的用途就是叉乘可以用来计算法线

3. 两个物体之间的距离和方向

两个向量a,b相减(a-b)的结果是得到一个新向量,从b指向a;反之亦然

var heading = target.position - player.position; // 1

1.得到player指向target的向量

var distance = heading.magnitude;// 2
var direction = heading / distance; // 3
  1. 得到这个向量的长度
  2. 所以,player向着目标点的方向就是长度/距离(Normalized magnitude)
    我们这样计算的目的是为了同时获得新向量的长度和标准化后的向量以便于下一步计算。这两个数值的计算都是cpu heavy的。因为他们的计算都需要开平方。
if (heading.sqrMagnitude < maxRange * maxRange) {
    // Target is within range.
}
  1. 有时我们只想知道方向,而不想知道player距离target有多远,为了避免计算magnitude,我们可以使用sqrMagnitude方法计算magnitude的平方,这样可以避免开方运算,节省cpu资源。This is much more efficient than using the true magnitude in the comparison.

4. 计算垂直vector

image.png

当给定空间中的3个点后,我们只需要从任意一个点出发,得到它到另外两个点的向量,然后对这两个向量做叉乘即可:

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


image.png

5.使用点乘

想象一辆车的码表,其速度计算依赖于车轮胎前进的方向,但是车子在某些情况下也有侧滑等情况出现,这时,码表计算时就应该把侧滑的速度也计算进去。我们可以通过rigidbody.velocist得到车子总体的位移情况,但为了将其投影到前向,我们可以使用点乘:

 var fwdSpeed = Vector3.Dot(rigidbody.velocity, transform.forward);

【参考文献】

  1. unity官方手册:Vector Cooknook
  2. Vector Maths - Unity Official Tutorials
  3. https://www.youtube.com/watch?v=wXI9_olSrqo&t=44s

你可能感兴趣的:(Unity中的向量(vector))