aabb碰撞只需检查x、y轴投影是否同时重叠:rect1.min.x ≤ rect2.max.x 且 rect2.min.x ≤ rect1.max.x,y轴同理;两条件均满足才相交,否则不相交。

用分离轴定理(SAT)的简化版直接判断AABB碰撞
AABB(Axis-Aligned Bounding Box)之间是否相交,根本不需要真正跑SAT——因为所有边都平行于坐标轴,只需检查两个矩形在x轴和y轴上的投影是否重叠。只要任一轴不重叠,就无碰撞;只有两个轴都重叠,才算碰撞。
关键点:不是“计算交点”,而是“排除不相交”。这比求交更高效、更稳定。
- 假设矩形用
min和max表示(即Vec2 min, max),则x轴重叠条件是:rect1.min.x = rect2.min.x - y轴同理:
rect1.min.y = rect2.min.y - 两式同时为真,才返回
true;任一为假,立即返回false(短路求值可省一半比较)
别用中心+半宽高结构写错边界条件
有人习惯用 center 和 halfExtents 表达AABB,这本身没问题,但容易在碰撞判断时写出错误的不等式。比如误写成 abs(center1.x - center2.x) —— 这个形式只在两矩形完全静止、无缩放/旋转时数学等价,但一旦涉及浮点误差或后续扩展(如加入z轴),极易出错。
更稳妥的做法是统一转为 min/max 形式再判断,哪怕多一次转换,也避免逻辑歧义。
- 从中心转
min/max:min = center - halfExtents; max = center + halfExtents - 不要在碰撞函数里混合两种表示,尤其不要把
center和另一个矩形的min直接混算 - 如果性能敏感且确定只用中心表示,至少确保使用
而非 <code>(防止浮点下刚好贴边却被判为不碰)
注意浮点精度导致的“贴边失效”问题
当两个AABB在某个轴上刚好“挨着”(比如 rect1.max.x == rect2.min.x),严格数学意义下它们不相交,但游戏逻辑中往往希望这种接触也算碰撞(比如角色站在地板上不能掉下去)。这时候需要引入一个极小的容差值 epsilon。
- 推荐容差值设为
1e-5f或std::numeric_limits<float>::epsilon()</float>(后者太小,通常不够用) - 修改x轴判断为:
rect1.min.x = rect2.min.x - epsilon - 容差必须加在不等式右侧,而不是对坐标做四舍五入——否则会破坏AABB语义(比如把本该在外部的点拉进内部)
- 切记:容差不能过大,否则会导致远距离“幽灵碰撞”,尤其在高速移动物体上会明显穿模
2D和3D版本只需扩展维度,别重复造轮子
2D AABB碰撞函数和3D的唯一区别就是多一个z轴判断。硬写两个函数不仅冗余,还容易维护不同步。C++模板能干净解决这个问题。
例如定义通用模板函数:
template<size_t n>
bool intersect(const std::array<float n>& min1, const std::array<float n>& max1,
const std::array<float n>& min2, const std::array<float n>& max2) {
for (size_t i = 0; i max2[i] + 1e-5f || max1[i] <p>调用时传 <code></code> 或 <code></code> 即可,逻辑一致、无分支、易测。</p>
<p>实际项目里最容易被忽略的,是没把容差和坐标系方向(Y轴朝上还是朝下)统一考虑——比如UI系统用Y朝下,而物理系统用Y朝上,同一个 <code>min.y/max.y</code> 含义可能翻转,这时光靠函数名无法暴露问题。</p></float></float></float></float></size_t>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











