基础几何知识

角的度量方式

角的度量方式分为角度(Degree)和弧度(Radian)两种。角度就是将一个圆形切成360份,每一份就是1度角。弧度是当弧长等于圆的半径时即为1弧度。

Unity 向量A的垂直向量_叉乘

角度弧度转换

Unity 向量A的垂直向量_游戏引擎_02

三角函数

在直角三角形中(下图为例),如果 a 、 b 、 c 、 x \ a、b、c、x a、b、c、x中的两个变量已知则能计算出另外两个变量的值。

Unity 向量A的垂直向量_Unity 向量A的垂直向量_03


计算公式

正弦: sin(x)=a/c (对比斜)

余弦: cos(x)=b/c (临比斜)

正切: tan(x)=a/b (对比临)

余切: cot(x)=b/a

正割: sec(x)=c/b

余割: csc(x)=c/a

反正弦: arcsin(a/c)=x

反余弦: arccos(b/c)=x

反正切: arctan(a/b)=x

已知一角和一边,求另外两边,用sin、cos、tan。
已知两边,求角,用arcsin、arccos、arctan。

常用三角函数值

Unity 向量A的垂直向量_游戏引擎_04


Unity 向量A的垂直向量_叉乘_05


使用方法

已知一个角和一条边,用 sin、cos、tan 。

已知两条边求角度,用 ArcSin、ArcCos、ArcTan 。

Unity应用

在代码中调用Mathf.Sin等三角函数方法时传入的参数并不是角度,而是弧度。

比如如果我们想要获取sin30度的值不能这样写:Mathf.Sin(30)。这样是错的。
正确的写法应该是Mathf.Sin(30 * Mathf.Deg2Rad),将角度转为弧度再传参,得到的结果就是0.5了。

下图为官方API的描述。

Unity 向量A的垂直向量_游戏引擎_06


要求输入的角度是以弧度为单位的,所以要用这些方法时经常要用到角度和弧度的转换。向量

向量是一个数字列表,表示各个维度上的有向位移。它是一个有大小有方向的物理量。大小就是方向的模长,方向描述了空间中向量的指向。向量可以用来表示物体的位置和方向。

Unity 向量A的垂直向量_叉乘_07


Unity 向量A的垂直向量_点乘_08

向量加减法

向量的加减就是向量对应分量的加减,类似于物理学中力的正交分解。

Unity 向量A的垂直向量_叉乘_09

向量相减

向量相减等于各分量相减。

Unity 向量A的垂直向量_Unity 向量A的垂直向量_10


几何意义:向量a与向量b相减,结果理解为以b的终点为起点,以a的终点为终点的向量。方向由b指向a。

注意:我们可以把向量相减理解为a、b终点的连接,但实际上该向量准确起始位置应该是坐标原点。

Unity 向量A的垂直向量_叉乘_11


实际应用:计算两点之间的距离和相对方向。

向量相加

向量相加等于各分量相加。

Unity 向量A的垂直向量_叉乘_12


几何意义:如下图,假设空间中有两个向量a和b,a与a’平行且长度相等,b与b’平行且长度相等。a+b就相当于a,b,a’,b’所围成的平行四边形的对角线。

Unity 向量A的垂直向量_unity_13


也可以这么说,由向量a的起点出发,沿着a的方向走a的长度,然后沿着b的方向走b的长度,达到的点相当于从a的起点沿着a+b的方向走a+b的长度。

实际应用:物体的移动。

向量与标量的乘除

Unity 向量A的垂直向量_游戏引擎_14


Unity 向量A的垂直向量_叉乘_15


实际应用:加速、减速、放大、缩小。

点乘

点乘又称点积或内积。表示为各分量的乘积和。

Unity 向量A的垂直向量_点乘_16


注意结果不是一个向量,而是一个标量(Scalar),可以是负数。

几何意义: a ⋅ b = ∣ a ∣ ∣ b ∣ cos ⁡ ( a , b ) 当a、b的模为1时,ab的点乘值为∠ab的cos值,再通过反余弦就可以获得角度。

// 计算点乘值
float dot = Vector3.Dot(a.position.normalized, b.position.normalized);
// 计算夹角
float angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

第一步计算点乘值,第二步计算夹角。

实际应用:计算两向量的夹角。

点乘常用结果:对于标准化后的向量,方向相同,则点乘为1;方向相反,则点乘为-1;互相垂直,则点乘为0。

Unity 向量A的垂直向量_unity_17


总结:点乘可以用于计算向量夹角,但只能用于计算内夹角,也就是小于180°的夹角。若想超过180°,则需要与叉乘结合。点乘的结果为单个数值。

叉乘

叉乘又称 “叉积” 或 “外积” ,与点乘结果不同,叉乘结果是一个向量,一个垂直于两个向量所组成平面的向量。模长为两向量模长乘积再乘夹角的正弦值。
公式:
[x1 , y1 , z1] × [ x2 , y2 , z2] = [ y1 ∗ z1 − z1 ∗ y2 , z1 ∗ x2 − x1 ∗ z2,x1∗y2 − y1 ∗ x2 ]
代码:Vector3 cross = Vector3.Cross(a.position, b.position);
注意:叉乘不需要加normalized,加不加都不会影响结果。

应用:

创建垂直于平面的向量;
判断两条向量的相对位置。

叉乘获得垂直向量

1.当 a 到 b 顺时针,则 a x b 朝上。

Unity 向量A的垂直向量_叉乘_18


2.当 a 到 b 逆时针,则 a x b 朝下。

Unity 向量A的垂直向量_点乘_19


也可以这样理解:当a、b顺时针夹角小于180时, a x b 朝上;当a、b顺时针夹角大于180时, a x b 朝下。

代码判断:叉乘结果 y > 0 ,则朝上,则小于180°;叉乘结果 y < 0 ,则朝下,则大于180°;

左手规则

a、b向量叉乘获得的垂直向量遵循左手规则,以下图为例:

Unity 向量A的垂直向量_Unity 向量A的垂直向量_20


以上图手势为标准,垂直于拇指a和食指b形成的平面的向量result就是a、b叉乘的结果。

叉乘计算角度

叉乘也可以用来计算角度,但只能计算0° ~ 90°。

// 计算叉乘结果,叉乘不需要加normalized,但加了也不会有影响
Vector3 cross = Vector3.Cross(a.position, b.position);

// 用叉乘结果换算角度
float angle = Mathf.Asin(cross.magnitude) * Mathf.Rad2Deg;

叉乘常用结果:

Unity 向量A的垂直向量_unity_21

计算360°以内的角(点乘结合叉乘)

点乘结合叉乘,可以计算出360°以内的角。

Unity 向量A的垂直向量_Unity 向量A的垂直向量_22

// 先用点乘计算角度(180°以内)
float dot = Vector3.Dot(a.position.normalized, b.position.normalized);
float angleX = Mathf.Acos(dot) * Mathf.Rad2Deg;
// 再用叉乘后的y值确定方向
Vector3 cross = Vector3.Cross(a.position, b.position);
if (cross.y < 0)
{
	angleX = 360 - angleX;
}

先用点乘计算角度(180°以内),再用叉乘后的 y 值确定方向,得数 angleX 为 a 顺时针到 b 的角度。