1. 碰撞检测基础

1.1 什么是碰撞检测?

碰撞检测,说白了就是判断两个物体有没有「碰到一起」。

我刚开始做游戏引擎时,觉得这玩意儿很简单——不就是判断两个形状是否重叠吗?后来才发现,这里面的坑比想象中多得多。

举个例子:一颗子弹以每秒1000米的速度飞向墙壁。在某一帧,子弹还在墙的左边;下一帧,它已经穿到墙的右边了。这就是经典的「隧道效应」。如果你只用简单的重叠判断,子弹就「穿模」了。

所以,碰撞检测不仅仅是「有没有碰到」,还包括「什么时候碰到」「在哪里碰到」「碰到的法线方向是什么」。这些信息,后续的碰撞响应机制全都要用。

核心定义: 碰撞检测是判断两个或多个几何体在空间上是否相交,并提取相交信息(时间、位置、法线)的过程。

1.2 为什么它如此重要?

没有碰撞检测的世界是什么样的?

  • 游戏里:角色会掉到地板下面,子弹会穿过敌人,汽车会互相「穿模」而过。
  • 物理仿真里:刚体会无限重叠,布料会穿透自身,流体粒子会乱飞。
  • 机器人领域:机械臂会撞到障碍物,AGV小车会「卡」在墙里。

我记得有一次做机器人仿真项目,碰撞检测没处理好,机械臂直接「穿」过了工作台。幸好是在仿真环境里,要是真机……嗯,那维修费够我吃半年泡面了。

避坑指南: 我曾经在一个物理沙盒项目中,因为碰撞检测的容差设得太小,导致两个静止物体一直在「微碰撞-分离-再碰撞」的循环中震荡。CPU占用率直接拉满,画面却纹丝不动。后来把容差调到合理范围,问题才解决。

1.3 应用领域一览

领域 典型场景 精度要求 实时性要求
游戏 角色碰撞、子弹命中、物理交互 中等(可接受近似) 极高(60fps以上)
物理仿真 刚体破碎、布料模拟、流体交互 中等
机器人 路径规划、避障、抓取 极高 取决于应用
CAD/CAM 装配干涉检查、碰撞分析 极高 低(离线计算)

你想想看,游戏里角色踩到地面,你不需要精确到微米级的碰撞点;但机器人抓取精密零件,差0.1毫米可能就报废了。这就是不同领域对碰撞检测的「容忍度」差异。

1.4 基本数学工具

做碰撞检测,数学是绕不开的。但别怕,常用的就三个工具:向量、点积、叉积。

1.4.1 向量

向量就是有方向的线段。在碰撞检测里,我们用它来表示位置、速度、法线方向。

// 二维向量
struct Vector2 {
    float x, y;
};

// 三维向量
struct Vector3 {
    float x, y, z;
};

// 向量减法:计算从A到B的方向
Vector3 direction = B - A;

我个人习惯把向量想象成「箭头」。箭头指向哪,力就往哪使。碰撞法线就是一个垂直于碰撞面的向量,它告诉物体「你应该往哪个方向弹开」。

1.4.2 点积

点积的计算公式很简单:a · b = |a| * |b| * cos(θ)。但在实际项目中,我更常用它的几何意义——判断两个向量的「朝向关系」。

// 点积
float dot(Vector3 a, Vector3 b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

// 判断两个物体是否相向而行
float relativeVelocity = dot(velocityA - velocityB, normal);
if (relativeVelocity < 0) {
    // 正在靠近,需要处理碰撞
}
实用技巧: 点积大于0,两个向量方向大致相同;小于0,方向相反;等于0,互相垂直。这个特性在碰撞检测中用来判断「物体是正在靠近还是远离」。

1.4.3 叉积

叉积的结果是一个垂直于两个输入向量的新向量。它的长度等于两个向量围成的平行四边形面积。

// 叉积(三维)
Vector3 cross(Vector3 a, Vector3 b) {
    return Vector3(
        a.y * b.z - a.z * b.y,
        a.z * b.x - a.x * b.z,
        a.x * b.y - a.y * b.x
    );
}

// 计算三角形的法线
Vector3 edge1 = B - A;
Vector3 edge2 = C - A;
Vector3 faceNormal = normalize(cross(edge1, edge2));

叉积在碰撞检测里最常用的场景就是计算法线。比如一个三角形面片,用两条边做叉积,就能得到垂直于这个面的法线方向。

三个工具总结:
  • 向量:表示位置、速度、方向
  • 点积:判断朝向、计算投影长度
  • 叉积:计算法线、计算面积

1.5 知识体系总览

下面这张图,是我做碰撞检测时脑子里始终绷着的一根弦。它把整个知识体系串了起来:

碰撞检测 定义与核心概念 重要性 应用领域 几何相交判断 相交信息提取(时间/位置/法线) 隧道效应与连续碰撞检测 游戏:防止穿模 仿真:保证物理正确性 机器人:避免真实损坏 游戏引擎(Unity/Unreal) 物理仿真(Houdini/Blender) 机器人(ROS/MoveIt) 数学工具:向量 · 点积 · 叉积 碰撞检测知识体系总览

这张图把碰撞检测拆成了四个维度:定义、重要性、应用领域、数学工具。我个人习惯在开始一个新项目前,先对着这张图捋一遍思路——「我要检测什么?精度要求多高?用什么数学工具?」想清楚了再动手,能少走很多弯路。

我的建议: 刚开始学碰撞检测,别急着上复杂的算法。先把向量、点积、叉积这三个工具练熟。我见过太多人一上来就研究GJK算法,结果连法线方向都算反了。基础不牢,地动山摇。

公众号:蓝海资料掘金营,微信 deep3321