抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

简介

本文主要阐述胶囊体之间的碰撞检测原理和实现方式。

原理

胶囊体的表示

我们使用 5 个参数来表示一个胶囊体。

  1. center:胶囊体的中心位置。
  2. height: 胶囊体中间圆柱部分的高度,本文使用 data.extents.y 来代替。
  3. radius:胶囊体的上下半圆部分的半径。
  4. rotation:胶囊体的旋转角度。
  5. 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;
}
}

项目地址

更新日志

2024-05-19

  1. 修复胶囊体检测 bug。

2024-03-05

  1. 修改错别字。

2024-03-05

  1. 更新胶囊体检测基础内容。

评论