引言
检测到碰撞只是第一步(我们在几何章节讨论了检测),更重要的是响应 (Response)。 物体是反弹?是停下?还是滑行?这取决于物理材质的属性:弹力 (Bounciness) 和摩擦力 (Friction)。
1. 反射向量 (Reflection Vector)
最常见的响应是“反弹”。例如光线反射、台球撞击。 我们需要根据入射向量 \(\vec{v}\) 和碰撞表面的法线 \(\vec{n}\) 计算出反射向量 \(\vec{r}\)。
公式如下: \[ \vec{r} = \vec{v} - 2(\vec{v} \cdot \vec{n})\vec{n} \]
推导: 1. \(\vec{v}\) 在法线方向的分量是 \((\vec{v} \cdot \vec{n})\vec{n}\)。 2. 要反转这个分量,我们需要减去它两次(一次抵消,一次反向)。
代码实现:
// Unity 内置函数
Vector3 reflection = Vector3.Reflect(velocity, hitNormal);
// 手动实现
Vector3 Reflect(Vector3 v, Vector3 n) {
return v - 2 * Vector3.Dot(v, n) * n;
}2. 弹性与非弹性碰撞
现实世界中,能量总会损耗。我们引入一个恢复系数 (Coefficient of Restitution, \(e\)),通常称为 Bounciness。
\[ \vec{v}_{new} = \vec{r} \times e \]
- \(e = 1\): 完全弹性碰撞(超级弹力球,永远不停止)。
- \(e = 0\): 完全非弹性碰撞(一坨泥巴贴在墙上)。
- \(0 < e < 1\): 真实的物理模拟。
3. 冲量 (Impulse)
对于更复杂的刚体碰撞(如两个移动的球体相撞),直接修改速度是不够的,我们需要考虑质量。 我们施加一个瞬间的力,称为冲量 \(J\)。
\[ J = \Delta p = m \Delta v \]
基本思路是: 1. 计算相对速度。 2. 如果物体在分离,则忽略。 3. 计算所需的冲量大小 \(j\)。 4. 将冲量应用到两个物体上(遵循牛顿第三定律,方向相反)。
4. 摩擦力 (Friction)
当物体沿表面滑动时,摩擦力会减慢切线方向的速度。 摩擦力方向总是与运动方向相反。
\[ F_f = -\mu N \] 其中 \(\mu\) 是摩擦系数,\(N\) 是正压力。
在游戏中,我们通常简单地将切线速度乘以一个衰减系数:
// 简单的摩擦模拟
velocity *= (1.0f - friction * dt);总结
- 反射向量是实现反弹效果的核心,依赖于点积。
- 恢复系数控制反弹的能量损耗。
- 简单的游戏可以直接修改速度,复杂的物理引擎使用冲量求解器。