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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容