前言
游戏中,我们常会对物体是否碰撞进行检测,之前我只是会用AABB,但对其原理并没有做太多理解,今天来尝试学习一下。
一维
一维中,假设给出两条线段,如何判断其是否重叠呢?
我们理解一下,一条线段的长度范围,是其右端点减左端点,由于数轴从左到右逐渐增大,因而我们称右端点为最大点,左端点为最小点,两线段的关系我们只考虑相交与不相交的情况可得。
不相交
如果A和B不相交,那么其实只有两种情况
1.A在B的右边
此时,B的最大点一定小于A的最小点
2.A在B的左边
此时,B的最小点一定大于A的最大点
那么我们就可以得出一个逻辑。
如果 B的最大点小于A的最小点 或 B的最小点大于A的最大点,那么A和B必定不相交
既然线段的关系只有相交和不相交,那么对上面取反,我们就可以得到相交是怎样的判断。
当然,也可以直接对相交进行判断,但是相交的判断情况要比不相交多得多,大家有兴趣可以自己试试。
二维
讨论完了一维后,我们其实就可以顺着这个思路去讨论二维了。
二维中,无非就是多加了一个数轴,我们看这个图
对于二维空间上的任一矩形,我们可以得到其在数轴上的投影,比如A有Ax和Ay,B有Bx和By
这样,其实我们就把问题简化为了在两个一维的数轴上的线段的比较
X轴
Y轴
无论X轴还是Y轴,都只有两种情况:相交或不相交
而且将其组合,即可得所有的情况有2 × 2 = 4种
1.X轴相交,Y轴不相交
2.X轴不相交,Y轴不相交
3.X轴相交,Y轴相交
4.X轴不相交,Y轴不相交
这就是全部情况了,我们画图来看看
1.X轴相交,Y轴不相交
2.X轴不相交,Y轴不相交
3.X轴相交,Y轴相交
4.X轴不相交,Y轴不相交
由上述图片,我们可以得出,在二维中,如果两矩形要相交,那么必须满足X轴和Y轴同时相交。
我们逆思维思考一下,是不是就是说只有X轴或者Y轴任一不相交,那么两矩形便不相交?
这样不相交的判断就呼之欲出了,还记得上面一维的不相交判断么,放到二维就是:
x = Bx的最大点小于Ax的最小点 或 Bx的最小点大于Ax的最大点
y = By的最大点小于Ay的最小点 或 By的最小点大于Ay的最大点
如果 x 或 y 有任一成立,则两矩形不相交,相信你也明白代码要怎么写了。
三维
其实有以上一维和二维的铺垫,三维无非就是再加一个轴而已,我们尝试直接推。
x = Bx的最大点小于Ax的最小点 或 Bx的最小点大于Ax的最大点
y = By的最大点小于Ay的最小点 或 By的最小点大于Ay的最大点
z = Bz的最大点小于Az的最小点 或 Bz的最小点大于Az的最大点
如果 x 或 y 或 z 有任一成立,则两立方体不相交,直接秒了,更高维也就是加轴加轴加轴了!
三维立方体代码BeLike
public static bool IsCollision(Collider boxA, Collider boxB)
{
Vector3 minA = boxA.Position + boxA.Center - boxA.Size * 0.5f;
Vector3 maxA = boxA.Position + boxA.Center + boxA.Size * 0.5f;
Vector3 minB = boxB.Position + boxB.Center - boxB.Size * 0.5f;
Vector3 maxB = boxB.Position + boxB.Center + boxB.Size * 0.5f;
if (maxA.x < minB.x || minA.x > maxB.x)
return false;
if (maxA.y < minB.y || minA.y > maxB.y)
return false;
if (maxA.z < minB.z || minA.z > maxB.z)
return false;
return true;
}