unity底层运行机制_深入理解Unity的碰撞检测机制

unity的检测流程

碰撞检测,就是检测两个物体是否相交,如果物体非常规则,比如球体,直接检测圆心距离是否小于半径和即可,计算量十分小,但是,如果物体不规则,比如一个角色,进行十分细致的碰撞检测就会变的十分困难,这时候,我们一般会用简单几何体去逼近复杂网格

image.png

如上图所示,我用4个圆去逼近一个多边形,注意,下层圆圆心位于根圆到顶点连线上,且圆心位于上层圆边上的,类比到3d空间也是如此,可以用球体去趋近网格,这里需要注意,凹多边形的逼近是难计算的,所以内部会将其拆分成多个凸多边形

image.png

现在,假如有两个物体,那么,我们只需要检测这两个物体是否相交即可,如果有3个物体a,b,c ,那么,我们要比较ab ac bc,如果有四个物体abcd,我们要比较ab ac ad bc bd cd,可见,有n个物体,我们要比较(n-1)+(n-2)……+(1)次,

如果物体相当多,那么比较次数也会及其可怕。

为了解决这个问题,unity里使用了空间划分技术,目前主流的划分技术有BSP,BHV,八叉树,四叉树

这几种算法都用到了树结构,下面分别简单介绍一下

BSP:BSP是一个二叉树结构

首先选定一个面作为根节点(一般会选两侧物体数量大致相同的面),然后遍历物体,如果物体在此面正面,将其加入到左子节点,如果在反面,加入到右子节点,如果和此面相交,加入左右两个子节点,之后,将左右子节点作为新的根节点进行递归,

构建完成后,在检测时,只要检测同一叶子节点的所有物体就行了

image.png

这里注意,检测物体位于哪面一般使用长方体来进行近似的,大家用unity的时候可能也注意到,gameobject有width和height两个属性,这两个属性很可能是用来进行划分的

BHV:将相邻的物体放在一个圆内,检测时只要检测同一个圆内的

image.png

八叉树,四叉树

image.png

这两个其实原理相同,上面是四叉树,类比到3d空间就是八叉树

这时,我们可以发现,如果碰撞体位移了,或者碰撞网格改变了,树的结构也会随之变化,这里我猜测,unity内部会有静态和动态两种树,静态树时预先计算好的,而动态树则会在有物体位移时重新计算,而动态树很可能也有相关优化,比如子物体多的物体会单独维护一个树,再将其作为动态树的子树

而这里有个问题,物体位移时树是会改变的,碰撞不会出现问题。但碰撞网格在运行时改变的话,碰撞会失效,如果我们动态生成一个物体,为其加入网格碰撞器,那么,它仍然不会有碰撞检测,可能是由于树没有更新,也有可能逼近算法没有执行,解决办法是,生成物体后,调用Setactive(false),然后Setactive(true)

在OnEnable里,会调用函数生成对网格进行碰撞检测所需的信息

image.png

接下来说一下连续碰撞检测的问题,上图说明了不同collisiondectection的物体是否进行连续检测

连续检测算法大概有下面几种

比如说某物体的位移随时间变化为y=vt

unity里每次检测相隔0.02s,那么,假如上帧时间为0,这帧时间为0.02,引擎可以将0.002,0.004,0.006……0.018,0.02分别带入方程,只要有一个检测到就说明有碰撞,但是unity里用的并不是这一种

计算量最小,从此帧到上帧的位置连一条线,检测这条线有没有碰撞检测

unity里很可能就是这种,因为文档里说,连续检测只适用于内置的

image.png

此方法将物体的轨迹视为一个碰撞体进行检测,比如

image.png

将球体的轨迹近似为一个胶囊体,然后对胶囊体进行碰撞检测

你可能感兴趣的:(unity底层运行机制)