先说下本篇博问的起因,在我的群里总有一些朋友在问,关于旋转,空间点判定等问题,关于这些程序实现上的问题,看完本篇后你会发现要解决也很简单。
本篇关键字:点乘 叉乘 弧度 角度 sin cos asin atan atan2

先抛砖引玉从点乘与叉乘开始

点乘 叉乘

这张图可以记一下,简单明了,仔细看下图里有画垂直与Y轴与X轴的红线。
dot - cross

使用场景: 光照计算

这边是diffuse的计算方式,这里用到的dot,判定法线是否与光源反射的方向同向。
如果两者同向反射光强度最高,反之则变暗。
演示-shaderforge

使用场景: 判定前后或左右

这段代码直接通过dot判定是否物体在我们的前或后。

1
2
3
4
5
6
7
8
9
var forward = transform.TransformDirection(Vector3.forward);
var toOther = other.position - transform.position;
Debug.Log($"在前方 ? {Vector3.Dot(forward, toOther) > 0}");
var right = transform.TransformDirection(Vector3.right);
var toOther = other.position - transform.position;
Debug.Log($"在右方 ? {Vector3.Dot(right, toOther) > 0}");

再稍微深入一点的概念

弧度 与 角度

rad - 弧度
deg - 角度

这个概念我常常见有人搞混,口语化描述弧度或者角度,我们都称之为度,所以经常会弄错。
有个简单的记忆方式:

1
2
3
一般unity中对Eular Angle进行操作的api用的都是角度而非弧度。
一般我们所有开放给人为配置的也都是角度(易读也好理解)
一般在三角函数相关计算api使用的是弧度。

Mathf.sin & cos

使用sin+cos计算一个指定的坐标

y轴为正前方夹角30度

使用场景: 角度转向量

角度转方向向量

1
2
3
4
5
6
7
public Vector3 OriToVec(float orientation)
{
Vector3 vector = Vector3.zero;
vector.x = Mathf.Sin(orientation * Mathf.Deg2Rad);
vector.z = Mathf.Cos(orientation * Mathf.Deg2Rad);
return vector.normalized;
}

Mathf.Asin

我这边用的是lua演示的,数学库运算结果都一样。

1
math.deg(math.asin(math.sin(math.rad(30)))) --result:30

Mathf.Atan & Mathf.Atan2

Mathf.Atan()返回的值的范围是[-π/2,π/2],Mathf.Atan2()返回的值的范围是[-π,π]。

1
math.deg(math.atan2(3,4)) --result: 36.869897645844

计算的夹角如图

在我眼中的数学在游戏中的应用

前人已经实现了很多数学函数库,只要把数学当作工具使用就行了。了解这个”工具“的性能,以及如何运用。那么你一定会做的很好。