想象你是一位婚宴总策划:几百位宾客、几十道菜、舞台灯光、桌椅摆放,全都挤在一个宴会厅里。如果每张桌子想怎么动就怎么动,每道菜想几点上就几点上,大厅立刻乱成一锅粥。物理引擎集成,就是给游戏世界请来一位同样称职的“总策划”——它规定每个物体怎么落、怎么撞、怎么堆,让角色踩得稳、石块滚得真、车辆漂得顺。 这篇文章要带你走进物理引擎的内部:从选型(PhysX 还是 Havok)、刚体模拟、物理材质、约束关节,到固定步长、碰撞加速和性能调优。全程用这场“婚宴筹备”打比方,你不需要任何物理或编程基础,只要跟着故事的节奏走,就能把物理引擎集成这件事的骨架搭起来。

岗位关联

对 AI 从业者而言,物理引擎是游戏开发、机器人仿真、世界模型数据合成的“真实感底座”。理解它的集成方式,意味着你能为 AI 提供物理正确的训练环境,也能在游戏 AI 项目中与引擎团队高效协作。

目录
  1. 可视化演示
  2. 引擎选型对比
  3. 刚体模拟世界
  4. 物理材质体系
  5. 约束与关节
  6. 固定步长策略
  7. 碰撞加速结构
  8. 性能优化调优
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示深入理解物理引擎集成的核心机制,通过架构/数据/状态/性能四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

深入理解物理引擎集成:Phys PhysX与Havok引擎集成 碰撞检测与约束配置 核心机制可视化 深入理解物理引擎集成整体架构与关键组件

引擎选型对比

筹备婚宴的第一步,是决定请哪支团队。PhysX 像是自带灯光特效团队的“科技婚庆公司”,背后有 NVIDIA 撑腰,GPU 加速能力出众,Unity 和 Unreal 引擎里都内置了它的模块,开箱即用;Havok 则像深耕行业几十年的“街坊老师傅”,不追求花哨,但内存占用低、在主机平台(PlayStation、Switch 等)上表现极其稳定,很多 3A 大作(如《塞尔达传说:旷野之息》)都曾用它撑起海量交互物。

选团队不能只看名气。你还得考虑厨师队伍是否熟悉你家灶台——对应游戏的目标平台;预算是否吃得住——对应商业授权费用;以及出了问题能不能找到人问——对应社区与文档生态。引擎的“跨平台考量”就是看它是否能在 PC、主机、移动端都稳定运行,避免出现“这场婚宴的舞台只适配了一个城市”的尴尬。

技术选型常用加权评分法,把多个维度折算成一个数字。假设你分别给性能(A)、平台适配(P)、社区生态(C)三项打 1-10 分,再减去授权成本(L)带来的扣分,就得到一个综合分 S,哪个引擎分高选哪个。

回到婚宴:你最终选定的团队,就是在“上菜速度、场地适配、售后响应、账单金额”之间找到平衡的那一位。引擎选型同理——没有绝对最好的物理引擎,只有最匹配你项目的物理引擎。

S=w1A+w2P+w3C−w4L\displaystyle S = w_1 A + w_2 P + w_3 C - w_4 L
这个公式的意义:把“感觉”变成“数字”。权重 w 表示你对各因素的重视程度,加起来通常等于 1。
  1. 计算性能贡献把性能评分 A 乘以权重 w₁。权重越大,说明你越在意跑得够不够快。
    w1Aw_1 A
  2. 累加平台贡献把平台适配分 P 与社区生态分 C 各自加权后相加,代表“换设备不翻车”和“出问题有人帮”的价值。
    w2P+w3Cw_2 P + w_3 C
  3. 扣除授权成本减去 w₄L,把商业授权费、移植改造成本作为负分处理,防止被“看起来很美的方案”带偏。
    −w4L- w_4 L
  4. 得到综合得分三者合起来就是候选引擎的总分,最终排序择优。
    S=w1A+w2P+w3C−w4LS = w_1 A + w_2 P + w_3 C - w_4 L

刚体模拟世界

选定承办团队后,宴会厅正式布场。每一张桌子、每一把椅子、每一坛酒,在物理引擎里都是一个“刚体”(Rigid Body)。刚体是“绝对不会变形的物体”的简化假设:现实中的纸箱会凹陷,但游戏里为了算得快,先假设所有物体都像陶瓷花瓶一样硬。刚体还需要搭配“碰撞形状”(Shape),它决定了物体占多大空间——就像给每件家具量好尺寸,碰撞检测才能知道两张桌子是否快贴上了。

刚体还有两个重要属性:质量与惯性。质量决定“推不推得动”,惯性决定“转不转得起来”。同样重量的一根长杆和一个小球,转起来费力的程度完全不同。物理引擎里有个特殊成员叫“运动学刚体”(Kinematic Body),它像被领班亲自推着走的展示餐车:不响应重力,也不能被人推走,但可以按脚本匀速移动,还会把挡路的东西顶开——正是移动平台、自动门的最佳人选。

所有刚体的运动都遵循牛顿第二定律:力 = 质量 × 加速度。引擎每个模拟步都在重复“算合力 → 更新速度 → 更新位置”的循环。为了让数值稳定,通常采用半隐式欧拉积分:

宴会厅的布场公式,其实就是“每张桌椅该往哪挪”的流水账:先算清受力,再定新速度,最后落新位置。只要每个物体都按这套规矩走,大厅里就不会出现椅子凭空挤进桌子的名场面。

vn+1=vn+a Δt\displaystyle \mathbf{v}_{n+1} = \mathbf{v}_n + \mathbf{a}\,\Delta t
xn+1=xn+vn+1 Δt\displaystyle \mathbf{x}_{n+1} = \mathbf{x}_n + \mathbf{v}_{n+1}\,\Delta t
通俗说:先用加速度把“新速度”算出来,再用“新速度”去移动位置。因为用的是最新的速度,所以比“先走再加速”更不容易把物体弹飞。
  1. 计算新速度当前速度 vₙ 加上加速度 a 乘以时间步 Δt,得到下一时刻的速度 vₙ₊₁。
    vn+1=vn+a Δt\mathbf{v}_{n+1} = \mathbf{v}_n + \mathbf{a}\,\Delta t
  2. 计算新位置把新速度 vₙ₊₁ 乘以时间步 Δt,加到当前位置 xₙ 上。注意这里用的是“已经更新过的速度”。
    xn+1=xn+vn+1 Δt\mathbf{x}_{n+1} = \mathbf{x}_n + \mathbf{v}_{n+1}\,\Delta t
  3. 理解半隐式因为位置更新使用了最新速度,模拟自带阻尼效果,能量不容易积累爆炸。
    xn+1=xn+vn+1 Δt\mathbf{x}_{n+1} = \mathbf{x}_n + \mathbf{v}_{n+1}\,\Delta t

物理材质体系

婚宴的菜好不好吃,取决于食材特性:果冻要够弹,糙米饭要够粘。物理材质(Physics Material)就是给物体的“口感”定参数,其中最重要的两个是摩擦系数与恢复系数。摩擦系数管“滑不滑”——像桌面粗糙程度,系数大,杯子推过去很快就停;系数小,冰块能在桌面上溜很远。摩擦又分静态与动态:静止时需要的“启动推力”更大,动起来后维持滑动反而更省力。

恢复系数管“弹不弹”:它描述两个物体碰撞后,沿碰撞方向的相对速度能保留多少。系数为 1 是完美弹性(像理想台球),系数为 0 是完全非弹性(像两团黏土黏在一起)。当两个不同材质的物体相撞时,引擎按“组合规则”(取平均、取最小、相乘等)算出一个综合系数。

设碰撞前两物体相对速度为 v_rel,碰撞后相对速度为 v'_rel,恢复系数定义为:

想想那盘果冻:掉到桌上会回弹好几下,因为恢复系数高;而那锅糯米饭摔地上就“趴”住了,因为恢复系数接近 0。给物体配好“材质菜单”,物理世界才有真实的手感。

e=−vrel′vrel\displaystyle e = -\frac{v'_{\text{rel}}}{v_{\text{rel}}}
负号表示“速度方向反转”:撞前是靠近,撞后是分开,所以加个负号让 e 保持为正。
  1. 确定碰撞前相对速度沿碰撞法线方向,计算两个物体接近的速度差值。
    vrel=vA−vBv_{\text{rel}} = v_{A} - v_{B}
  2. 确定碰撞后相对速度碰撞结束后,同样沿法线方向计算两者的速度差值。
    vrel′=vA′−vB′v'_{\text{rel}} = v'_{A} - v'_{B}
  3. 取比值并加负号用碰撞后除以碰撞前,取相反数。e=1 表示完全弹性,e=0 表示完全吸收。
    e=−vrel′vrel\displaystyle e = -\frac{v'_{\text{rel}}}{v_{\text{rel}}}

约束与关节

婚宴流程表写着:伴娘必须站在新娘身旁、香槟塔一层叠一层不能倒。物理引擎也有类似的规定,叫“约束”(Constraint)。最常见的约束类型:距离约束(两个物体之间距离固定,像用一根看不见的杆连着)、铰链约束(只允许绕一个轴旋转,像门)、球窝约束(允许任意方向旋转,像人的肩关节)、滑动约束(只能沿一条轨道移动,像抽屉)。

约束的本质是“修正”。每次物理步长结束后,引擎检查各约束有没有被违反:比如距离约束被拉长了 1 厘米,就沿约束方向施加一个“修正力”,把物体推回正确位置。但一个约束的修正可能同时破坏另一个约束——香槟塔的瓶子和底座互相拉扯。所以引擎要用“求解器迭代”(Solver Iterations):像调音师反复拧琴弦,一轮不够拧两轮,通常迭代 4~10 次后误差就小到肉眼看不见。

约束求解器中,每次迭代都在把一个标量 λ(拉格朗日乘子)沿约束方向投影到速度上。简化后的速度修正公式为:

流程表上的每一条规矩,都是一道约束;每一个反复核对的司仪,都是一次求解迭代。迭代次数够多,香槟塔才会稳稳当当;次数太少,整桌杯子就会在观众眼前“塌方”。

v′=v−J vJM−1JT M−1JT\displaystyle \mathbf{v}' = \mathbf{v} - \frac{J\,\mathbf{v}}{J M^{-1} J^{\mathrm{T}}}\, M^{-1} J^{\mathrm{T}}
J 是约束的“方向感受器”,M 是质量矩阵。公式意思是:把速度中违反约束的那部分挑出来,按质量加权推回去。
  1. 提取违反约束的速度Jv 表示当前速度在约束方向上“跑偏了多少”。
    J vJ\,\mathbf{v}
  2. 计算质量加权系数分母 JM⁻¹Jᵀ 表示“把这个速度推回去需要克服多少惯性”,质量越大分母越小,修正就越迟钝。
    JM−1JTJ M^{-1} J^{\mathrm{T}}
  3. 生成修正动量分数值乘上 M⁻¹Jᵀ,得到实际要施加的速度修改量。
    J vJM−1JT M−1JT\frac{J\,\mathbf{v}}{J M^{-1} J^{\mathrm{T}}}\, M^{-1} J^{\mathrm{T}}
  4. 叠加回原速度从当前速度 v 中减去修正量,得到满足约束的新速度 v'。
    v′=v−J vJM−1JT M−1JT\mathbf{v}' = \mathbf{v} - \frac{J\,\mathbf{v}}{J M^{-1} J^{\mathrm{T}}}\, M^{-1} J^{\mathrm{T}}

固定步长策略

婚宴后厨有个铁律:不管宾客多着急,每批菜固定 20 分钟出一锅,绝不为“催单”而加快火候。物理引擎也一样:渲染帧率可能忽高忽低(电脑卡顿时 30 帧,流畅时 120 帧),但物理模拟必须用“固定时间步长”(Fixed Timestep),比如恒定 1/60 秒一次。因为求解器的数值结果依赖步长,步长一变,物体弹跳高度、堆叠稳定性全都会变——就像菜没熟透就出锅,味道每次都不一样。

实现上使用“累计器”(Accumulator):每帧把真实流逝时间加入累计器,然后循环执行固定步长的物理更新,直到累计器剩余时间不够一步为止。剩余的时间留到下一帧用。为了让渲染画面不出现“一顿一顿”,引擎对刚体位置做插值(Interpolation),把上一步和下一步的位置平滑过渡。

固定步长还有一层“防隧穿”的意义:如果一步移动的距离超过了薄墙的厚度,高速小球可能直接穿墙而过——就像一列火车瞬间穿过一节车厢。固定步长 + 限制最大速度,是避免这类“瞬移穿模”的基本盘。后厨稳住了出菜节奏,宾客的体验就稳了;引擎稳住了物理步长,游戏世界的真实感就稳了。

acc←acc+Δtframe\displaystyle \text{acc} \leftarrow \text{acc} + \Delta t_{\text{frame}}
while acc≥h:physicsStep(h),  acc←acc−h\displaystyle \text{while } \text{acc} \ge h: \quad \text{physicsStep}(h),\ \ \text{acc} \leftarrow \text{acc} - h
h 是固定步长。while 循环保证物理永远按 h 的整数倍前进,渲染帧率再乱也不影响物理稳定性。
  1. 累加真实时间把这一帧渲染消耗的真实时间 Δt_frame 加入累计器 acc。
    acc←acc+Δtframe\text{acc} \leftarrow \text{acc} + \Delta t_{\text{frame}}
  2. 判断是否够一步只要累计器大于等于固定步长 h,就执行一次物理更新。
    acc≥h\text{acc} \ge h
  3. 执行并扣减调用 physicsStep(h) 推进物理世界,然后把用掉的 h 从累计器中减去,继续循环。
    physicsStep(h),  acc←acc−h\text{physicsStep}(h),\ \ \text{acc} \leftarrow \text{acc} - h

碰撞加速结构

婚宴大厅里几百位宾客同时走动,要让每个人都精确知道“我和谁快撞上了”,最笨的办法是两两互相确认——几百人两两配对就是几万次询问,直接卡死。物理引擎的解决思路是分层筛选:先“宽相”(Broadphase),再“窄相”(Narrowphase)。

宽相阶段用简单的几何体快速排除明显不相交的物体对,常用 AABB(轴对齐包围盒)——把每个物体用一个尽量贴合的方盒子包起来,比较盒子是否重叠,就像婚宴接待处先看名单分区,把明显不在同一区的人排除掉。窄相阶段才对候选物体对做精确判定:球与球的精确交点、网格与三角形的逐面检测,得出真正的接触点与法线。

实现宽相有一个经典算法叫“Sweep and Prune“(扫描-排序):把所有物体的 AABB 边界沿 x 轴排序,然后像拉链一样线性扫描,只检查排序后相邻的物体对。排序的复杂度是 O(n log n),远优于暴力遍历的 O(n²)。另一种常用方案是”空间哈希”:把空间切成小格子,每个物体查它所在格子及相邻格子里的邻居。

宽相是“名单粗筛”,窄相是“当面确认”。有了这份高效名单,几千块碎砖从楼上炸开时,引擎才能在一帧之内理清它们各自要撞什么——大厅里的宾客再多,也不会乱成一团。

Tbroad=O(nlog⁡n)\displaystyle T_{\text{broad}} = O(n \log n)
n 是场景中的动态物体数。log n 来自排序:就像婚宴名单按姓氏排好后,你翻页查找的速度远快于从头挨个问。
  1. 理解为什么要排序把 n 个盒子的边界按坐标排序,只需 O(n log n) 次比较,就能获得“谁和谁可能在附近”的候选信息。
    O(nlog⁡n)O(n \log n)
  2. 对比暴力法如果不排序而两两检查,需要 n(n-1)/2 次比较,复杂度为 O(n²),物体一多就爆炸。
    O(n2)O(n^2)
  3. 扫描相邻对排序后线性扫描相邻区间,把重叠的盒子对送入窄相,这里最坏还是 O(n²),但实际场景中重叠对极少。
    O(n+m)O(n + m)

性能优化调优

婚宴进行到后半场,厨房必须保证上菜动线顺畅:已经上完菜的灶台立刻关火,不常用的食材提前备好,多个炉灶同时开工。物理引擎的性能优化,就是这套厨房动线设计。

第一招是“刚体休眠”(Sleeping)。当刚体的线速度与角速度低于某个阈值,并持续一段时间(比如 0.5 秒),引擎就把它标记为休眠:不再参与物理模拟,直到被其他物体撞醒。就像关掉空灶台——静止的箱子堆、停稳的车,不再消耗任何算力,直到有人踢它们一脚。大批量物体场景中,休眠能省下 80% 以上的计算量。

第二招是“并行任务”(Parallel Jobs)。物理引擎的宽相、窄相、求解器都是高度可并行的:多核 CPU 像多个灶台同时开工,把几千个碰撞对分给不同线程处理。第三招是“场景降级”(LOD):远处的小物件用更简单的碰撞形状(盒子代替精细网格)、更低的迭代次数;就像后厨对不重要的配菜只做简单摆盘,把精力留给主菜。最后,配合 Profiler(性能分析器)找到瓶颈阶段,对症下药。

整体开销由三部分构成:

物理引擎调优的本质,是把算力花在“看得见、摸得着”的物体上。灶台该关就关,备菜该早则早,分工该细就细——婚宴不乱,游戏也不卡。

Ttotal=Tbroad+Tnarrow+Tsolve\displaystyle T_{\text{total}} = T_{\text{broad}} + T_{\text{narrow}} + T_{\text{solve}}
T_broad 是粗筛、T_narrow 是精细碰撞、T_solve 是约束求解。休眠让物体不再进入这三项流程,并行让每个流程内部更快。
  1. 列出总开销每帧物理总耗时等于三个阶段耗时的加和,定位瓶颈就看哪一项占比最大。
    Ttotal=Tbroad+Tnarrow+TsolveT_{\text{total}} = T_{\text{broad}} + T_{\text{narrow}} + T_{\text{solve}}
  2. 理解宽相成本T_broad 随物体数的对数增长,物体多了它最先承受压力。
    Tbroad=O(nlog⁡n)T_{\text{broad}} = O(n \log n)
  3. 理解休眠收益休眠刚体直接移出所有阶段,相当于把 n 变小,总耗时随活跃物体数 m 重新计算。
    Ttotal=O(mlog⁡m),m<nT_{\text{total}} = O(m \log m),\quad m < n

AI 应用场景

游戏 AI 的物理感知与决策

阶段:环境交互与目标感知

解决的问题:传统游戏 AI 常靠“预写脚本”模拟投掷与躲避,遇到障碍物时表现生硬。接入物理引擎后,AI 可以用“碰撞形状投射”预判手雷扔出去会撞到哪面墙、弹到哪个方向,再据此规划路线,行为自然很多。

具体案例:在射击游戏中,AI 敌人投掷闪光弹前,先用窄相检测做一次快速弹道模拟:判断首个碰撞点的房檐会把手雷弹向何处,若弹回自己脚下则放弃投掷改走侧翼。这套逻辑让 AI 的“战术智商”与真实物理一致。

机器人强化学习的物理仿真环境

阶段:训练数据生成

解决的问题:真实机器人试错成本极高,摔一次可能损坏硬件。用 PhysX 或 Havok 搭建仿真环境,让策略网络在虚拟刚体世界中训练,再迁移到真实机器人(Sim-to-Real),成本低且可并行。

具体案例:四足机器人控制策略在仿真中训练时,每个回合随机化摩擦系数与恢复系数(地面从草地到冰面),让策略学会应对不同材质组合律下的打滑与弹跳,最终在真实地形上成功行走。

世界模型视频生成的数据引擎

阶段:预训练数据合成

解决的问题:视频生成模型常生成“球穿墙、物体悬浮”等违反物理的镜头,本质是训练数据缺乏因果一致性。物理引擎可以作为数据合成器,为世界模型提供一批“运动轨迹严格符合刚体碰撞与约束”的标注视频。

具体案例:训练短视频生成模型时,用固定步长 1/240 秒的物理仿真渲染 10 万段“小球撞击积木塔”的视频,每段都带有逐帧速度与碰撞标记;模型学习后生成的视频中,倒下的积木不再穿模,也自然不会再飘浮。

Python 演示

python41 行
"""Simplified 2D physics demo: fixed-timestep bouncing balls."""import math  class Ball:    def __init__(self, x, y, rest):        self.x = x        self.y = y        self.vy = 0.0        self.rest = rest  # restitution coefficient        self.bounces = 0     def update(self, dt, g, ground):        self.vy += g * dt        self.y += self.vy * dt        if self.y >= ground - 5:            self.y = ground - 5            self.vy = -self.vy * self.rest            self.bounces += 1            if abs(self.vy) < 30:                self.vy = 0.0  def simulate(balls, dt, steps, g=980.0, ground=500.0):    """Advance physics with fixed sub-steps."""    sub = dt / steps    for _ in range(steps):        for b in balls:            b.update(sub, g, ground)  if __name__ == "__main__":    a = Ball(100, 100, 0.90)    b = Ball(300, 100, 0.30)    t = 0.0    while t < 3.0:        simulate([a, b], 0.02, 2)        t += 0.02        if int(t * 100) % 50 == 0:            print("t=%.2f va=%.1f vb=%.1f" % (t, a.vy, b.vy))    print("a bounces=%d b bounces=%d" % (a.bounces, b.bounces))
目的:用固定步长子步模拟两颗恢复系数不同的小球自由落体与反弹,直观对比“材质”如何影响弹跳次数,复现正文中恢复系数公式的行为。
  1. self.vy = -self.vy * self.rest碰撞瞬间速度反向并乘以恢复系数,对应 e = -v'/v。恢复系数 0.9 的球反弹速度大,0.3 的球很快就停下。
  2. if abs(self.vy) < 30: self.vy = 0.0速度低于阈值时进入“休眠”状态,对应正文的刚体休眠优化,防止小球永远微弹。
  3. sub = dt / steps把 0.02 秒的物理步再切成更小的子步,避免高速时一步跨过地面造成隧穿。
  4. while t < 3.0:` 配合 `simulate([a, b], 0.02, 2)固定步长每次推进 0.02 秒,模拟结果与后续打印频率无关,体现“帧率无关”的物理推进方式。
  5. int(t * 100) % 50 == 0每 0.5 秒打印一次速度,便于观察两种材质球的衰减差异。

常见误区

误区我每帧调用一次物理更新,把 `deltaTime` 传给引擎,游戏不卡时物理就准确,这不挺好吗?

正解渲染帧率是波动的——卡顿时 30 帧,流畅时 120 帧。若直接把每次的 deltaTime 当步长,物理求解器每次步长都不一样,物体弹跳高度和堆叠稳定性都会漂移,就像同一道菜每次火候都不同。正确做法是用累计器按固定步长推进,渲染再快,物理也是一步一步走。

为何常见:因为“一帧调用一次”的写法最直观,很多入门教程也这么写,初学者很少意识到物理与渲染的解耦需求。

误区给小球设置恢复系数 1.5,它就会像打了鸡血一样越弹越高,看起来很爽。

正解恢复系数定义在 [0,1] 区间,e=1 表示完全弹性碰撞,动能无损失;大于 1 意味着碰撞后相对速度大于碰撞前,系统能量凭空增加,物理引擎会造成“自激震荡”,物体越弹越高甚至飞上天。这相当于婚宴上的弹跳床,宾客越跳越疯,最终失去控制。设置超过 1 的恢复系数是调试事故,不是特效。

为何常见:直觉上“弹性=能量大”,把动画里的夸张弹跳当成了物理常识,忽略了能量守恒。

误区既然隧穿是大步长引起的,那把步长调到 1/1000 秒总没错吧?无脑缩步长就行。

正解步长过短会让每帧需要执行的物理步数暴涨,CPU 开销成倍增加;而且求解器迭代次数不足时,更短的步长也拯救不了堆叠抖动。稳定性的关键在“步长与速度匹配”:限制最大速度、增加求解器迭代、启用 CCD(连续碰撞检测)都是比单纯缩步长更有效的方案,就像后厨缩短出菜时间不是靠把火开到最大。

为何常见:数值分析中“步长越小越精确”的印象深入人心,但实时物理还要权衡算力与迭代收敛,不存在“无脑越小越好”。

误区物体用 AABB 包围盒碰撞,盒子看着差不多方方正正的,这应该就是精确的物理碰撞了吧?

正解AABB 只是宽相阶段的粗糙筛子——它只能告诉你“两个盒子可能重叠”,但盒子里实际装的是球、是圆柱还是复杂网格,全靠窄相阶段逐面计算。若跳过窄相,汽车撞到人形 NPC 时会按方盒子判定,出现“隔空撞人”的尴尬效果。宽相负责“可能”,窄相负责“精确”,两者缺一不可。

为何常见:碰撞检测的知识点常从 AABB 讲起,初学者容易把“第一步”当成“全流程”,忽略了后面还有更精细的窄相计算。

误区文档说运动学刚体“不受力”,那它应该被任何物体直接穿过,也不会制造任何碰撞反应吧?

正解运动学刚体不受重力与冲力,但它的动画驱动速度是显式设置的,且它仍然参与碰撞:一个匀速移动的平台会把站在上面的玩家顶起来,也会把挡路的箱子推走。它像被领班推着的餐车——餐车本身不自己发力,但谁挡着它,它就把谁挤开。正确理解是“不受力但影响碰撞”,不是“与物理无关”。

为何常见:“不受力”的字面意思容易让人误以为它和静态障碍物一样只是摆设,忽略了它“显式运动+主动碰撞”的组合特性。

面试题

Q1. 恢复系数 e=0.6 表示碰撞后:

单选题 · easy

  • A.法向相对速度保留 60%← 正确答案
  • B.切向速度保留 60%
  • C.总能量保留 60%
  • D.刚体质量变为 60%

答案:A。恢复系数定义在法线方向,是碰撞后与碰撞前相对速度的比值(取负),e=0.6 表示法向相对速度保留 60%。切向速度由摩擦决定,总能量不是线性保留,质量与恢复系数无关。就像果冻回弹的是“撞过来的那一下”,不是所有方向的动量。

Q2. 固定时间步长的核心好处是:

单选题 · easy

  • A.物理结果与渲染帧率解耦← 正确答案
  • B.让每一帧画面渲染更快
  • C.降低游戏的内存占用
  • D.自动提升屏幕分辨率

答案:A。固定步长保证物理求解器每步用时一致,与渲染帧率的波动无关,从而获得稳定可复现的物理行为。它不直接提升渲染速度或内存表现,更与分辨率无关。相当于后厨固定 20 分钟出一锅,不管外面宾客排队多乱,菜品的火候始终一致。

Q3. 高速小球穿过薄墙的常见原因是:

单选题 · mid

  • A.单步位移超过墙的厚度← 正确答案
  • B.重力加速度设置过大
  • C.恢复系数设置得过高
  • D.刚体质量设置得太小

答案:A。当固定步长内物体的位移大于碰撞体的厚度时,宽相与窄相都可能错过接触,产生隧穿。重力、恢复系数或质量不会直接导致穿透,只影响速度或反弹幅度。这就像一列飞驰的火车一下穿过了整节车厢,因为你检查它位置时它已经跳过了车厢中段。

Q4. Broadphase 阶段的主要职责是:

单选题 · mid

  • A.快速排除明显不相交的物体对← 正确答案
  • B.精确计算接触点的世界坐标
  • C.生成场景的渲染网格
  • D.求解约束的迭代修正

答案:A。宽相用 AABB 等粗略形状快速筛选候选碰撞对,把明显不相交的排除掉,降低计算量;精确接触点属于窄相,网格生成属于渲染,约束修正是求解器的工作。就像婚宴接待处先按名单分区筛人,不必每个人都当场核对身份证。

Q5. 刚体进入休眠状态的常见条件是:

多选题 · mid

  • A.线速度与角速度低于阈值并持续一段时间← 正确答案
  • B.被其他运动物体撞飞之后立即休眠
  • C.与静态地面接触时自动休眠← 正确答案
  • D.只要启动时速度为零就永远休眠

答案:AC。休眠需要速度低于阈值并保持一段时间,且通常要求与稳定接触面(如地面)接触。被撞飞瞬间速度高不会休眠;启动时速度为零但悬空或受力会醒,移动平台经过时也会唤醒它。正确姿势是“静止且无人打扰才关火”,一旦有人踢一脚灶台立刻重启。

Q6. Havok 物理引擎的突出优势通常是:

单选题 · mid

  • A.内存占用低且主机平台适配成熟← 正确答案
  • B.完全开源且免费商用
  • C.仅支持 GPU 物理加速
  • D.自动生成整套美术资源

答案:A。Havok 是老牌商业引擎,以内存效率高、主机平台(PS/Switch)表现稳定著称,常见于 3A 游戏。它并非免费开源,也不是只走 GPU 加速,更不会自动生成美术资产。选它更像请一位账目精打细算、熟悉本地厨房的老师傅。

Q7. 固定步长模拟中,渲染插值(Interpolation)的作用是:

单选题 · mid

  • A.让物体位置在渲染帧之间平滑过渡← 正确答案
  • B.提高物理求解的数值精度
  • C.减少碰撞检测的候选物体对
  • D.降低刚体休眠的响应延迟

答案:A。渲染插值是在两个物理快照之间对位置做线性混合,让低帧率下的画面也不抖。它不改变物理精度,不参与碰撞检测,也不影响休眠判定。相当于后厨出菜节奏不变,但传菜员在走廊里用小碎步把菜端得更稳。

Q8. 提高求解器迭代次数(Solver Iterations)的直接效果是:

单选题 · hard

  • A.约束收敛更准但每步开销增大← 正确答案
  • B.渲染帧率一定会提升
  • C.刚体的质量自动增大
  • D.宽相碰撞对数量减少

答案:A。迭代次数越多,多个约束之间的耦合修正越充分,堆叠稳定性越好,但每次物理步的计算量随之上升。它不影响渲染性能,不改变质量,也不减少宽相候选对(那是加速结构的职责)。就像司仪多核对几遍流程,婚礼更稳但更耗时。

Q9. 下列哪些属于物理引擎的常见约束类型:

多选题 · mid

  • A.距离约束与铰链约束← 正确答案
  • B.颜色约束与光照约束
  • C.材质约束与贴图约束
  • D.球窝约束与滑动约束← 正确答案

答案:AD。距离约束固定间距、铰链约束限制旋转轴、球窝约束允许任意旋转、滑动约束限定直线轨道,都是物理约束。颜色、光照、材质、贴图属于渲染或美术范畴,与刚体模拟无关。约束好比婚宴流程表上的硬规矩,而不是菜品的摆盘风格。

Q10. 关于运动学刚体(Kinematic Body),正确的描述是:

单选题 · easy

  • A.不受力但可显式设置速度并参与碰撞← 正确答案
  • B.完全不受碰撞影响可被直接穿过
  • C.只用于静态地面与墙壁
  • D.会受重力影响自动下落

答案:A。运动学刚体不响应力与重力,但位置由用户/动画显式控制,且会参与碰撞把动态刚体推开。它既不是虚拟物体,也不只用于静态场景,更不会自动下落。像被领班推着的展示餐车,自己不动脚,但谁挡路就顶开谁。