游戏中的数学

1.游戏中的矢量

  • 矢量的加减

公式:

a+b=(a₁+b₁,a₂+b₂,a₃+b₃)
a-b=(a₁-b₁,a₂-b₂,a₃+b₃)

示意图:

exp1

作用:游戏中可用于计算玩家a到怪物b的位移。

  • 矢量的点积

公式:

a.b=(a₁,a₂,a₃).(b₁,b₂,b₃)=a₁b₁+a₂b₂+a₃b₃
a.b=|a||b|cosθ

示意图:

exp2

作用:由结果而言,a.b就是a在b方向上的投影,公式2发现小于90度,点积大于0;等于90度,点积等于0;大于90度,点积小于0。所以通过点积可以判断游戏对象的朝向关系(比如接近面对面或背对背说明点积是小于0的)。

  • 矢量的叉积

公式:

a.b=(a₁,a₂,a₃)X(b₁,b₂,b₃)=(a₂b₃-a₃b₂,a₃b₁-a₁b₃,a₁b₂-a₂b₁)
a.b=|a||b|sinθ

示意图:

exp3

作用:可得到平面的法向量(也就是垂直向量),如果构不成平面,向量就是平行关系。在游戏中点积可以做到的,叉积都可以实现,并且比点积用处更多(因为点积返回的是标量,叉积返回的是法向量)。

2.游戏中的矩阵

  • 矩阵类别

方块矩阵:行列数相同的矩阵。

对角矩阵:Mᵪᵧ矩阵下x!=y都是0,不然随意。

单位矩阵:Mᵪᵧ矩阵下x==y都是1,不然都是0。

倒置矩阵:Mᵗ上标t用来表示矩阵倒置,经过倒置第n行变成第n列。

逆矩阵:矩阵与它的逆矩阵相乘可以得到单位矩阵,说明矩阵可逆,行列不为0的矩阵都有它的逆矩阵。

正交矩阵:矩阵与它的倒置矩阵相乘可以得到单位矩阵,说明矩阵是正交矩阵。

  • 矩阵的意义

矩阵的几何意义就是变换,点和矢量都可以画出来,这样矩阵可以画出来嘛,画是画不出来的,但是可以表现出来,比如Unity中对模型进行缩放、移动、旋转操作,第一个反应就是这些操作就是矩阵变换。3*3的矩阵可以用来表示所有的线性变换(可以保留矢量加和标量乘的变换就是线性变换),旋转和缩放就是线性变换,但是平移是没有办法表示。所以就出现齐次坐标给它扩展出一个维度,这个变换称为仿射变换(合并了线性变换和平移变换的变换),齐次坐标其实没有这么神奇,简单的来说只是为了统一处理缩放、移动、旋转,方便计算的一种表示方式而已。Unity内部用到矢量都会转换成列矩阵,所以本篇文章的矢量都用列矩阵来表示。

  • 平移矩阵示意图:

exp4

  • 缩放矩阵示意图:

exp5

  • 旋转矩阵示意图:

x轴旋转θ->

exp6

y轴旋转θ->

exp7

z轴旋转θ->

exp8

3.在Unity中实战

讲了这么多理论上的东西,没有实际上的表现,是比较难理解的或比较枯燥的,接下来就在Unity中进行实现,今天的主角就是小白块,不通过Unity提供接口去实现小白块的缩放、移动、旋转(直接使用矩阵变换去实现),具体代码如下:

using UnityEngine;
public class MatrixOfCube : MonoBehaviour
{
    public Matrix4x4 matrix4X4;
    // Start is called before the first frame update
    void Start()
    {
        matrix4X4.SetTRS(transform.position,
                         transform.rotation,
                         transform.localScale);

        MatrixTranslate();//矩阵平移
        transform.position = matrix4X4.GetColumn(3);

        MatrixScale();//矩阵缩放
        transform.localScale = new Vector3(matrix4X4.m00, matrix4X4.m11, matrix4X4.m22);

        //MatrixRotation();//矩阵旋转与60度对比一下即可理解
    }

    void MatrixTranslate()//矩阵平移
    {
        //构建平移(3,4,5)的矩阵
        Matrix4x4 tmp = Matrix4x4.identity;
        tmp.m03 = 3;
        tmp.m13 = 4;
        tmp.m23 = 5;

        matrix4X4 = matrix4X4 * tmp;
    }

    void MatrixScale()//矩阵缩放
    {
        //构建8倍的矩阵
        Matrix4x4 tmp = Matrix4x4.identity;
        tmp.m00 = 8;
        tmp.m11 = 8;
        tmp.m22 = 8;

        matrix4X4 = matrix4X4 * tmp;
    }

    void MatrixRotation()//矩阵旋转
    {
        //构建x轴旋转60度的矩阵
        Matrix4x4 tmp = Matrix4x4.identity;
        tmp.m00 = 1; 
        tmp.m11 = Mathf.Cos(60f * Mathf.Deg2Rad);
        tmp.m12 = -Mathf.Sin(60f * Mathf.Deg2Rad);
        tmp.m21 = Mathf.Sin(60f * Mathf.Deg2Rad);
        tmp.m22 = Mathf.Cos(60f * Mathf.Deg2Rad);
        tmp.m33 = 1;

        matrix4X4 = matrix4X4 * tmp;
    }
}

把脚本挂载到cube上,运行一下就可以知道矩阵变换在游戏中的原由了。

解决疑问

1.为什么缩放、移动、旋转需要使用矩阵变换呢?

不通过矩阵变换也是可以实现这些操作的,比如平移直接改变它的x,y,z即可,对于旋转来说需要确定旋转方向、旋转角度、旋转轴,将三个参数传递给定义好的接口然后实现旋转(可能接口内部会有比较复杂的if-else),这样为什么需要用到矩阵变换呢?因为我们都没有写过游戏引擎(如果有大佬写过,估计不会看这篇文章了),有这些疑问还是很正常的。首先用矩阵变换的原因是处理起来更加便捷(比如需要旋转,直接使用旋转矩阵即可,不需要三个参数和接口实现的复杂化),其次是为了统一处理(平移就使用平移矩阵,缩放使用缩放矩阵,性能上也没有任何区别,所以统一使用矩阵来表示各种变换)。

2.为什么3D空间的平移不能用3*3的矩阵?

问题本质和(n)D空间为什么不能用n*n的矩阵是一样的,有疑问的童靴可以尝试使用3*3矩阵计算一下平移变换,这里给出简单的图,用矩阵公式验证一下就知道了:

exp9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值