本节摘要:接触点上的冲量沿法向推开两物体,并因力臂产生角速度变化。有效质量把“这一点沿法向有多容易被推动”收成一个标量,冲量大小等于速度误差除以有效质量。恢复系数进入目标相对速度,鲍姆加特偏置进入穿透修复。写对这一条,顺序求解器只是把它套在循环里。
阅读完本节,你应当能够:
弹跳球对无限质量地面:v.n = -e * v.n。两刚体、还有旋转,就要问:沿法向补多少冲量 j,才能让相对法向速度变成目标值。相对速度
vrel = (vA + wA × rA) - (vB + wB × rB) vn = dot(vrel, n)
目标 vn_target = -e * vn(接近时),或 0(低速当非弹性)。需要的法向速度变化 dv = vn_target - vn。冲量 j = dv / K,K 是有效质量的倒数(有人把 K 叫有效质量,符号要在代码里写死一种)。施加:
vA += j * n * invMA wA += invIA * (rA × (j * n)) vB -= j * n * invMB wB -= invIB * (rB × (j * n))
静态地面 invMB=0、wB=0,退回弹跳球。符号错一次,两物体互相吸引,这是第一周最常见的 bug。画 n 从 B 指向 A,j 为正表示推开。

有效质量怎么来:冲量 j 引起的法向相对速度变化是 j 乘一个标量 K,
K = invMA + invMB + n · (invIA (rA × n) × rA) + n · (invIB (rB × n) × rB)
二维里叉积是标量,公式更短。K 接近 0 表示沿该方向推不动(两个静态体),跳过约束。K 很大表示很轻或力臂很长,同样 j 引起的速度变化大。
| 项 | 作用 |
|---|---|
| invM | 越轻越容易被推开 |
| 旋转项 | 接触点离质心远,拧起来容易,有效质量变小 |
| 锁定轴 | 对应 inv 置 0,K 变小,更“硬” |
恢复系数 e 不要对已经几乎静止的接触使用,否则永远睡不着。若 vn > -threshold(正在缓慢接近或已分离),把 e 当 0,目标速度 0。threshold 约 1 m/s 量级,按游戏手感调。分离中的接触 vn >= 0 且没有穿透要修,法向冲量应钳在 0——不能把物体再吸回去。这就是 complementarity:要么有压力且不接近,要么分离且压力为 0。单次冲量先算无约束 j,再 j = max(j, 0)。累计冲量也要整体非负,4.2 节会把累计写清楚。
穿透修复:bias = penetration * beta / dt,目标速度再减去 bias(符号:我们希望 vn 变成分离为正的话,bias 要加到分离方向)。beta 0.1–0.2。穿透很深时钳制 bias 最大值,否则一帧内修正速度巨大,爆炸。位置投影可以辅助,但不要和很大的 bias 同时用满。
vn_target = if approaching_fast: -e * vn else 0 vn_target += bias_separate j = (vn_target - vn) / K j = max(j, 0) # 单次、无累计时
💡 关键直觉:有效质量是“这一点的惯性”。同样误差,轻物体、长力臂需要的冲量更小,因为它们更容易被改速度。公式除以 K,不是随便除以质量。
重力不要在接触里再加一遍。积分阶段已经加了重力。有人用“接触法向抵消重力”的显式力,和冲量叠床架屋。例外:睡醒判定可以看法向冲量是否在支撑重量,那是读 lambda,不是再加力。
切向相对速度 vt = vrel - n*vn。动摩擦冲量试图把 vt 刹到 0,但长度不能超过 mu * jn。单次接触可以先看法向再摩擦。旋转加上圆锥摩擦比二维复杂,4.2 展开。这里先保证法向对:无摩擦堆叠应稳定,箱子可以滑。
NaN 防护:K 小于 epsilon 跳过;n 未单位化先单位化;r 用世界坐标。施加后若速度变成 inf,多半是 invI 算错或 q 没归一导致惯性爆炸。
⚠️ 常见坑:用局部 r 叉世界 n,或把 j 乘到力再乘 dt。前者旋转乱,后者飞天。冲量直接改速度。
测试矩阵:
角速度钳制在冲量之后仍要做,细杆被撞会转得离谱。动量守恒测试:两动态体无外力碰撞,总动量应几乎不变(浮点误差内)。静体参与时动量可以进“大地”。
把 1.1 的反射函数删掉,换成这一节的 j。地面仍是哨兵刚体。行为应接近,但盒子现在会转。转起来后流形多点才有意义——单点冲量会拧。所以 4.1 必须和 3.3 一起验收:四点支撑的静止箱子,法向冲量之和应接近重量(质量×g,注意单位与 dt:lambda 常是冲量,重量对应的冲量是 mgdt)。若差很多,不是重力没加,就是接触没撑住在积分里往下掉又被 bias 拉上来,表现为抖动。
单位再核对:j 的单位是动量,lambda 在有的文献里是力。你的公式若从速度误差除以 K 来,得到的是冲量。不要和“力约束”文献混抄系数。注释写明:本引擎 lambda 是冲量。
把盒子质心抬高,在底边角上施加同样法向冲量,角速度应更大,平动更小——因为杠杆项进了 K,同样速度误差需要的 j 更小,但角增量更大。把这个实验做成可视化:同一个 j 画平动箭头和转动弧。新人能凭这个记住“K 不是质量”。
符号表写进代码注释并保持:n 从 B 指向 A;j>0 推开;相对速度 A 减 B;bias 使穿透减小,即让 vn 朝分离为正方向增加。每次改公式对照这张表。组员各自发明符号,代码会有一半吸引接触。
恢复系数曲线:用球砸地,e=0、0.3、0.6 测弹起高度。高度不应超过释放高度。超过说明能量注入,查是否把重力在接触里又加了一次,或 j 乘了 dt。e=1 时高度应略低于释放高度(数值耗散)。略高则有 bug。
静止支撑:质量 10 的箱子 dt=1/60,重力 9.81,每步需要的法向冲量约 10*9.81/60。打印 lambda 之和对比。差一个 dt,多半把冲量当力或把力当冲量。这个数字验收比看“好像托住了”可靠。
旋转接触:在离质心远处的点碰撞,盒子应转。若不转,r 叉乘没写或 r 用了零向量。画 r 从质心到接触点,必须落到十字上。
与 n 从 B 指向 A 配套。vn<0 表示接近。符号表写进注释。组员若改成 B 减 A,必须同时翻 n,否则吸引。
两静态或沿该方向完全锁死,除以 K 会爆。跳过这条约束。细杆最小惯量下限也是为了让 K 别极端。
否则永远睡不着,微弹。阈值约 1 米每秒量级,按手感调。堆叠场景尤其要。
差一个 dt:冲量当力或反过来。差很多且抖动:接触没托住,积分往下掉又被 bias 拉回。先对账再看绘制。
法向不对时做摩擦是在错误法向上刹车。先无摩擦堆稳,再切向。顺序能省一天调试。
吸引。画箭头。
盒子不转。十字必须落在 r 终点。
能量注入。查重力是否加了两次或 j 乘 dt。
永不睡眠。阈值当 0。
inf。跳过约束。
冲量力混用。
错误方向刹车。先无摩擦堆稳。
转起来质量会变的感觉。先画轴。
先写 2D 再写 3D 适用于「01-刚体动力学与冲量响应」里所有几何麻烦事。二维金字塔、二维绳、二维铰链能看见点的增减。三维裁剪 bug 极难看,会让你怀疑人生。二维过了再加一根轴。 本条对应「01-刚体动力学与冲量响应」第 1 号备忘,和相邻条目不要合并成一句空话,分开验收。
「01-刚体动力学与冲量响应」不要在热路径调用脚本。求解器迭代十次回调十次,缓存和确定性一起死。标记事件,步末再发。这是布局问题也是架构问题。 本条对应「01-刚体动力学与冲量响应」第 2 号备忘,和相邻条目不要合并成一句空话,分开验收。
对账数字比观感先行。静止支撑冲量是否接近质量乘重力乘 dt,自由落体一秒是否接近四点九米,两球对心是否交换速度。「01-刚体动力学与冲量响应」相关实现先过对账,再谈好看。 本条对应「01-刚体动力学与冲量响应」第 3 号备忘,和相邻条目不要合并成一句空话,分开验收。
「01-刚体动力学与冲量响应」出抖动时按清单:时间步是否固定、流形点是否闪、法向是否跳、恢复系数是否在静止时仍生效、bias 是否过大、迭代是否其实在清零热启动。不要先把摩擦系数调到十。 本条对应「01-刚体动力学与冲量响应」第 4 号备忘,和相邻条目不要合并成一句空话,分开验收。
空间结构必须在世界系。把「01-刚体动力学与冲量响应」绑到摄像机或屏幕格子,逻辑和确定性都会在转视角时崩。渲染剔除不能代替宽相,看不见的物体仍能被撞到。 本条对应「01-刚体动力学与冲量响应」第 5 号备忘,和相邻条目不要合并成一句空话,分开验收。
「01-刚体动力学与冲量响应」的预分配策略:按关卡上限留容量,超出打日志并降级,不要在 step 中途默默扩容。扩容是卡顿尖峰,也是回放时分配顺序不同导致的潜在分叉源。 本条对应「01-刚体动力学与冲量响应」第 6 号备忘,和相邻条目不要合并成一句空话,分开验收。
把「01-刚体动力学与冲量响应」相关的失败做成最小复现:关掉渲染特效、关掉音频、只留固定 dt 的 step 和一份输入日志。能在十秒内重放出来的 bug 才叫被抓住。不能重放就先补录制,再谈修。很多人在这一步省时间,后面用几天陪着偶发抖动。 本条对应「01-刚体动力学与冲量响应」第 7 号备忘,和相邻条目不要合并成一句空话,分开验收。
在「01-刚体动力学与冲量响应」路径上加计数器要进 step 末尾快照,不要在热循环里格式化字符串。计数器本身若分配内存,你会优化一个被测量污染的世界。发布版可用宏剥掉绘制,但计数器的定义要保留,方便线上开一个极轻的统计开关。 本条对应「01-刚体动力学与冲量响应」第 8 号备忘,和相邻条目不要合并成一句空话,分开验收。
下一节把这一条公式放进循环:很多接触互相拉扯时,轮流投影,直到大家大致都合法。