2025-11-30 · game_math
【游戏中的数学】游戏中的数学 (6) - 距离与检测
详解欧几里得距离与曼哈顿距离的区别,平方距离优化技巧,以及点到直线、点到平面的距离计算方法。
相交检测 (Intersection Test) 是物理引擎的心脏。 它回答了“子弹是否击中敌人?”、“玩家是否站在地面上?”等问题。
射线由一个起点 \(O\) 和一个方向 \(D\) 定义:\(R(t) = O + D \cdot t\) (\(t \ge 0\))。
球体方程:\(|P - C|^2 = r^2\)。 将射线方程代入球体方程,会得到一个关于 \(t\) 的一元二次方程: \[ at^2 + bt + c = 0 \]
通常我们只关心最小的正解 \(t\),那是最近的击中点。
将射线代入平面方程 \(\vec{n} \cdot P + d = 0\)。 \[ \vec{n} \cdot (O + D \cdot t) + d = 0 \] 解出 \(t\): \[ t = \frac{-(\vec{n} \cdot O + d)}{\vec{n} \cdot D} \]
注意分母 \(\vec{n} \cdot D\): - 如果接近 0,说明射线与平面平行,无交点。 - 如果 > 0,说明射线从背面射出(通常不检测)。
这是最简单也是最快的碰撞检测形状。 它由两个点定义:\(min(x,y,z)\) 和 \(max(x,y,z)\)。 “轴对齐”意味着盒子不能旋转,永远平行于世界坐标轴。
两个 AABB 相交,当且仅当它们在 X、Y、Z 三个轴上都重叠。
bool Intersect(AABB a, AABB b) {
return (a.min.x <= b.max.x && a.max.x >= b.min.x) &&
(a.min.y <= b.max.y && a.max.y >= b.min.y) &&
(a.min.z <= b.max.z && a.max.z >= b.min.z);
}这是物理引擎中宽阶段 (Broad Phase) 碰撞检测的核心算法,用于快速剔除不可能相撞的物体。
将 AABB 看作是三组平行的平面(X轴一对,Y轴一对,Z轴一对)。 射线必须穿过所有三组“板 (Slab)”的重叠区域才算击中盒子。 这通常涉及计算 \(t_{min}\) 和 \(t_{max}\) 在三个轴上的最大值和最小值。
bool RayIntersectsAABB(Vector3 origin, Vector3 dir, AABB box, out float tMin) {
float tmin = float.NegativeInfinity;
float tmax = float.PositiveInfinity;
for (int i = 0; i < 3; i++) { // X, Y, Z 三个轴
if (Mathf.Abs(dir[i]) < 1e-6f) {
// 射线平行于该轴的 slab
if (origin[i] < box.min[i] || origin[i] > box.max[i])
{ tMin = 0; return false; }
} else {
float invD = 1.0f / dir[i];
float t1 = (box.min[i] - origin[i]) * invD;
float t2 = (box.max[i] - origin[i]) * invD;
if (t1 > t2) (t1, t2) = (t2, t1); // 确保 t1 < t2
tmin = Mathf.Max(tmin, t1);
tmax = Mathf.Min(tmax, t2);
if (tmin > tmax) { tMin = 0; return false; }
}
}
tMin = tmin;
return tmin >= 0;
}AABB 的限制是不能旋转。对于旋转过的物体,可以使用: - OBB (Oriented Bounding Box):带旋转的包围盒,检测需要用分离轴定理 (SAT),比 AABB 复杂但更精确。 - 胶囊体 (Capsule):线段 + 半径,非常适合角色碰撞体。检测实质是”两个线段的最短距离 < 半径之和”。 - 凸包 (Convex Hull):使用 GJK 算法检测两个凸体的相交,是物理引擎窄阶段 (Narrow Phase) 的核心。
如何判断一个点 \(P\) 是否在三角形 \(ABC\) 内部? 这需要用到重心坐标 (Barycentric Coordinates)。
任意点 \(P\) 都可以表示为三角形三个顶点的加权和: \[ P = uA + vB + wC \] 其中 \(u + v + w = 1\)。
如果 \(P\) 在三角形内部,那么必须满足: \[ 0 \le u, v, w \le 1 \]
复杂的网格碰撞(Mesh Collider)通常太慢,游戏开发中会尽量用组合的 AABB 或球体来近似。
< 上一篇: 距离与检测 | 回到目录 | 下一篇: 运动学基础 >
把当前热点继续串成多页阅读,而不是停在单篇消费。
2025-11-30 · game_math
详解欧几里得距离与曼哈顿距离的区别,平方距离优化技巧,以及点到直线、点到平面的距离计算方法。
2025-11-30 · game_math
碰撞响应完全指南:从反射向量到动量守恒,推导双体碰撞冲量公式,实现库仑摩擦模型,并用台球碰撞实例贯穿全部知识点。
2025-11-30 · game_math
详解游戏引擎中常用的标量数学函数:Lerp, InverseLerp, Remap, Clamp, SmoothStep 等。不仅有公式,更有实际应用场景。
2025-11-30 · game_math
深入浅出地讲解游戏开发中的三角函数:Sin, Cos, Atan2。从单位圆原理到圆周运动、波浪动画和朝向计算的实际应用。
相交检测 (Intersection Test) 是物理引擎的心脏。 它回答了“子弹是否击中敌人?”、“玩家是否站在地面上?”等问题。
射线由一个起点 \(O\) 和一个方向 \(D\) 定义:\(R(t) = O + D \cdot t\) (\(t \ge 0\))。
球体方程:\(|P - C|^2 = r^2\)。 将射线方程代入球体方程,会得到一个关于 \(t\) 的一元二次方程: \[ at^2 + bt + c = 0 \]
通常我们只关心最小的正解 \(t\),那是最近的击中点。
将射线代入平面方程 \(\vec{n} \cdot P + d = 0\)。 \[ \vec{n} \cdot (O + D \cdot t) + d = 0 \] 解出 \(t\): \[ t = \frac{-(\vec{n} \cdot O + d)}{\vec{n} \cdot D} \]
注意分母 \(\vec{n} \cdot D\): - 如果接近 0,说明射线与平面平行,无交点。 - 如果 > 0,说明射线从背面射出(通常不检测)。
这是最简单也是最快的碰撞检测形状。 它由两个点定义:\(min(x,y,z)\) 和 \(max(x,y,z)\)。 “轴对齐”意味着盒子不能旋转,永远平行于世界坐标轴。
两个 AABB 相交,当且仅当它们在 X、Y、Z 三个轴上都重叠。
bool Intersect(AABB a, AABB b) {
return (a.min.x <= b.max.x && a.max.x >= b.min.x) &&
(a.min.y <= b.max.y && a.max.y >= b.min.y) &&
(a.min.z <= b.max.z && a.max.z >= b.min.z);
}这是物理引擎中宽阶段 (Broad Phase) 碰撞检测的核心算法,用于快速剔除不可能相撞的物体。
将 AABB 看作是三组平行的平面(X轴一对,Y轴一对,Z轴一对)。 射线必须穿过所有三组“板 (Slab)”的重叠区域才算击中盒子。 这通常涉及计算 \(t_{min}\) 和 \(t_{max}\) 在三个轴上的最大值和最小值。
bool RayIntersectsAABB(Vector3 origin, Vector3 dir, AABB box, out float tMin) {
float tmin = float.NegativeInfinity;
float tmax = float.PositiveInfinity;
for (int i = 0; i < 3; i++) { // X, Y, Z 三个轴
if (Mathf.Abs(dir[i]) < 1e-6f) {
// 射线平行于该轴的 slab
if (origin[i] < box.min[i] || origin[i] > box.max[i])
{ tMin = 0; return false; }
} else {
float invD = 1.0f / dir[i];
float t1 = (box.min[i] - origin[i]) * invD;
float t2 = (box.max[i] - origin[i]) * invD;
if (t1 > t2) (t1, t2) = (t2, t1); // 确保 t1 < t2
tmin = Mathf.Max(tmin, t1);
tmax = Mathf.Min(tmax, t2);
if (tmin > tmax) { tMin = 0; return false; }
}
}
tMin = tmin;
return tmin >= 0;
}AABB 的限制是不能旋转。对于旋转过的物体,可以使用: - OBB (Oriented Bounding Box):带旋转的包围盒,检测需要用分离轴定理 (SAT),比 AABB 复杂但更精确。 - 胶囊体 (Capsule):线段 + 半径,非常适合角色碰撞体。检测实质是”两个线段的最短距离 < 半径之和”。 - 凸包 (Convex Hull):使用 GJK 算法检测两个凸体的相交,是物理引擎窄阶段 (Narrow Phase) 的核心。
如何判断一个点 \(P\) 是否在三角形 \(ABC\) 内部? 这需要用到重心坐标 (Barycentric Coordinates)。
任意点 \(P\) 都可以表示为三角形三个顶点的加权和: \[ P = uA + vB + wC \] 其中 \(u + v + w = 1\)。
如果 \(P\) 在三角形内部,那么必须满足: \[ 0 \le u, v, w \le 1 \]
复杂的网格碰撞(Mesh Collider)通常太慢,游戏开发中会尽量用组合的 AABB 或球体来近似。
< 上一篇: 距离与检测 | 回到目录 | 下一篇: 运动学基础 >
把当前热点继续串成多页阅读,而不是停在单篇消费。
2025-11-30 · game_math
详解欧几里得距离与曼哈顿距离的区别,平方距离优化技巧,以及点到直线、点到平面的距离计算方法。
2025-11-30 · game_math
碰撞响应完全指南:从反射向量到动量守恒,推导双体碰撞冲量公式,实现库仑摩擦模型,并用台球碰撞实例贯穿全部知识点。
2025-11-30 · game_math
详解游戏引擎中常用的标量数学函数:Lerp, InverseLerp, Remap, Clamp, SmoothStep 等。不仅有公式,更有实际应用场景。
2025-11-30 · game_math
深入浅出地讲解游戏开发中的三角函数:Sin, Cos, Atan2。从单位圆原理到圆周运动、波浪动画和朝向计算的实际应用。