简介
本文主要阐述胶囊体之间的碰撞检测原理和实现方式。
原理
胶囊体的表示
我们使用 5 个参数来表示一个胶囊体。
- center:胶囊体的中心位置。
- height: 胶囊体中间圆柱部分的高度,本文使用 data.extents.y 来代替。
- radius:胶囊体的上下半圆部分的半径。
- rotation:胶囊体的旋转角度。
- direction:胶囊体的竖直方向。
碰撞检测
胶囊体的碰撞检测,主要的原理和圆的碰撞检测差不多。我们可以把胶囊体看成多个圆心在一个线段上的球。我们只要找到两个胶囊体之间最近的两个线段上的点,就能用圆的碰撞检测判断两个胶囊体是否相交。
如图所示,判断两个胶囊体碰撞,我们主要判断 A 点和 B 点的圆是否相交。
现在我们的目标就很明确了,找出两个胶囊体最适合的检测点。
首先我们要找出两个胶囊体线段的最大值和最小值,通过如下计算可得到:
1 2 3 4 5 6
| Vector3 pointA1 = data1.center + data1.direction * data1.extents.y; Vector3 pointA2 = data1.center - data1.direction * data1.extents.y;
Vector3 pointB1 = data2.center + data2.direction * data2.extents.y; Vector3 pointB2 = data2.center - data2.direction * data2.extents.y;
|
然后我们计算两个胶囊体线段之间的最小距离,可以参考碰撞检测之线段检测的内容。
最后我们只需要进行圆与圆的碰撞检测就可以得到是否相交了。
代码
胶囊体碰撞检测1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private bool CollisionCapsule(CollisionData data1,CollisionData data2) { Vector3 pointA1 = data1.center + data1.direction * data1.extents.y; Vector3 pointA2 = data1.center - data1.direction * data1.extents.y;
Vector3 pointB1 = data2.center + data2.direction * data2.extents.y; Vector3 pointB2 = data2.center - data2.direction * data2.extents.y;
Vector3 closest1;
float distance = GetClosestDistanceBetweenLinesSqr(pointA1, pointA2, pointB1, pointB2);
float totalRadius = Mathf.Pow(data1.radius + data2.radius, 2); if (distance <= totalRadius) { return true; } else { return false; } }
|
项目地址
更新日志