定点数基于《工具篇:定点数运算数学库》的定点数库。

处理流程

1.读取配置:初始化碰撞环境

2.读取配置:初始化玩家碰撞体

3.FixedUpdate(具体看《Unity生命流程》):固定帧率检测碰撞发生

碰撞配置

ColldierConfig。

长方体类型:位置、长宽高、轴向。

圆柱体类型:位置、半径。

碰撞体

逻辑-视图分离

只维护逻辑值,视图则根据定点数逻辑值转换成浮点数来进行更新。但是,视图层更新后并不参与任何运算,只显示。

碰撞环境

环境初始化的前提是根据固定方式制作地图:只用 BoxCollider 和 CapsuleCollider 两种碰撞体,且全部放在一个EnvRoot结点下

初始化时,遍历这个根节点,将所有的BoxCollider转化为定点数长方体形碰撞体,将所有的CapsuleCollider转化为定点数圆柱体形碰撞体。

生成下来,放到一个List中保存。

碰撞检测+矫正计算(一对一)

Cylinder碰到Box

1.求出 向量OK = Cylinder.Pos - Box.Pos。

2.求出 向量OK 分别在 Box.X方向向量、Box.Z方向向量 上的投影的长度:

使用点乘即可。具体推导是线代问题,简单公式推导如下(向量v必须是方向向量也就是模为1):

3.对上面求出的2段投影的长度进行钳制,让他们的范围小于的Box的半长和半宽。

4.由3的两断钳制后的投影距离 + Box.Pos ,简单计算出P点(表面最近的接触点)位置。

5.判断P点是否在Cylinder内部,不在就不需要矫正直接返回;在就需要矫正,往PO方向矫正距离 Cylinder半径 - PO长度 即可。

6.如果需要矫正距离,那同时需要矫正速度方向,这可以利用向量的和来求出。求出 向量OV 在 向量PO 上的投影OT,和图中情况一致的话应该是个负数,用它可以求出 向量OT = 投影OT * 向量PO的单位向量。最后使用 向量OV - 向量OT ,得出向量TV,这就是修正后的方向向量。

Cylinder碰到Cylinder

两个圆求是否相撞,直接用 两者半径之和 与 两者圆心距离 比较即可。

至于计算矫正距离就比较简单了,公式我在图中给出了。最后计算矫正速度方向,方法和上面的6是一样的。

碰撞检测+矫正计算(一对多)

碰撞检测如图。

目前采用一个有微小误差的办法:
检测速度向量OV和向量和OB的夹角:角VOB,
与Max(角AOB,角COB)进行比较,

如果角VOB更小,那么就当作不需要矫正;
如果角VOB更大,那么就当作需要矫正。

如果不需要矫正,就当作墙体的反作用力完美抵消了速度V,撤销本次预执行的位置更新,方向修正为Vector.zero。
如果需要矫正,使用之前的方法(步骤6)求出 速度V 与 与法线夹角最大的那个向量的法线向量(AO)情况下的 修正方向。而矫正位置就很好算了,直接取所有碰撞点(一对一)的位置矫正之和。