
1. 项目概述从“穿模”的烦恼说起如果你正在用Unity开发游戏尤其是涉及到物理交互的部分那么“穿模”这个词对你来说一定不陌生。你精心设计的角色在高速移动时一头扎进了墙里你发射的子弹明明看着击中了目标却像幽灵一样穿了过去或者两个物体叠在一起时莫名其妙地就互相嵌入了。这些令人头疼的瞬间十有八九都跟Unity的刚体Rigidbody组件及其碰撞检测Collision Detection设置有关。刚体是Unity物理引擎的基石它让一个游戏对象GameObject受到重力、施加力等物理规则的影响。而碰撞检测则是决定这个物理对象如何“感知”并响应与其他碰撞体Collider接触的核心机制。很多开发者特别是刚接触Unity物理系统的新手往往只关注了给物体添加Rigidbody和Collider却忽略了Rigidbody组件上一个至关重要的下拉菜单——碰撞检测模式Collision Detection。这个看似简单的设置恰恰是解决高速物体穿模、微小碰撞失效等诡异问题的钥匙。今天我们就来彻底拆解Unity Rigidbody的三种碰撞检测模式Discrete离散、Continuous连续和Continuous Dynamic连续动态。我会结合近十年踩过的各种坑告诉你它们各自的工作原理、适用场景以及为什么选错了模式你的物体就会像个不守规矩的幽灵一样四处穿模。无论你是在做一款快节奏的射击游戏还是一个需要精密物理模拟的解谜游戏理解这些内容都能让你的项目物理表现更加稳定和可信。2. 核心原理碰撞检测到底在检测什么在深入三种模式之前我们必须先建立一个基本认知在计算机模拟中所谓的“碰撞检测”并不是一个连续不断的过程。游戏引擎包括Unity是以帧Frame为单位进行更新的。在每一帧里物理引擎会计算所有刚体的新位置然后检查它们是否与其他碰撞体发生了交集Intersection。如果检测到交集物理引擎就认为发生了“碰撞”并据此计算反弹力、摩擦力等在下一帧更新物体的速度和位置。这里就引出了最根本的问题物体是在两帧之间“运动”的但检测只发生在每一帧“定格”的时刻。想象一下用相机连拍一个飞驰的乒乓球。如果乒乓球速度太快在两张照片即两帧之间它可能已经从墙的一侧运动到了另一侧而相机没有拍到它接触墙壁的瞬间。在物理引擎看来这就意味着“没有发生碰撞”乒乓球会直接穿墙而过。这就是最典型的“穿模”Tunneling现象。Unity的碰撞检测模式本质上是在解决这个“采样”与“连续运动”之间的矛盾。不同的模式采用了不同的策略来弥补帧更新带来的信息缺失。2.1 物理更新与渲染更新的分离另一个关键点是理解FixedUpdate与Update的区别。Unity的物理计算是在固定的时间间隔默认为0.02秒即50Hz里在FixedUpdate调用之后进行的。而物体的位移变换Transform、动画和渲染则在每一帧的Update或LateUpdate中进行。这意味着一个物体在视觉上渲染帧可能移动得非常平滑但其物理状态位置、速度只在固定的物理时间步长里更新和检测。如果物体的速度非常高在一个物理时间步长内移动的距离超过其自身碰撞体的尺寸那么即使在两个物理步长之间它穿过了某个物体物理引擎也极有可能检测不到这次碰撞。三种碰撞检测模式可以看作是针对这种“高速穿越”问题的不同防御等级。3. 三种碰撞检测模式深度解析现在让我们进入正题逐一剖析Unity提供的三种模式。理解它们的差异是做出正确选择的前提。3.1 Discrete离散检测默认的“节能”模式这是Rigidbody的默认设置也是性能开销最小的一种模式。工作原理在每一个物理时间步长FixedUpdate结束时物理引擎会检查刚体在当前帧的位置与其在上一帧的位置之间是否存在一个静态的碰撞体。注意这里的检测是“离散”的它只关心起点和终点两个状态而不关心中间的运动路径。你可以把它想象成只检查旅行出发地和目的地而不关心沿途经过了哪里。优点性能最佳计算量最小对CPU最友好。适用于绝大多数情况对于移动速度相对较慢的物体例如行走的角色、缓慢推开的箱子、受重力下落的普通物体Discrete模式完全够用且高效。致命缺点与“穿模”场景 当刚体的运动速度过快时问题就来了。如果物体在一帧内移动的距离超过了其碰撞体在运动方向上的“厚度”它就有可能从一个碰撞体的一侧“跳”到另一侧而中间与碰撞体重叠的状态没有被检测到。典型场景1高速子弹。一颗子弹每帧移动10个单位而它的球形碰撞体半径只有0.5个单位。如果墙壁很薄子弹完全有可能在一帧内完成“未接触-部分重叠-完全穿过”的过程Discrete检测无法捕获中间的重叠状态导致穿墙。典型场景2快速移动的平台或角色。当玩家站在一个高速上下运动的平台上如果平台速度过快在某一帧玩家可能还在平台上方下一帧平台已经运动到玩家下方两帧之间没有重叠导致玩家跌落。典型场景3细小物体。即使速度不快但如果物体本身非常薄如一片纸、一个刀片它在运动方向上的“厚度”也很小更容易被离散检测所忽略。实操心得不要盲目地将所有刚体都设为Discrete。对于场景中静止的建筑物、缓慢移动的机关、大部分NPC使用Discrete是没问题的。但对于任何你认为“速度可能很快”或“体积可能很小”的物体就要提高警惕。3.2 Continuous连续检测为自身提供保护Continuous模式是针对“自身穿模”问题的一种解决方案。它的设计初衷是防止这个刚体本身穿过其他静态的或运动学Kinematic的碰撞体。工作原理这种模式会计算刚体从上一帧到当前帧的连续运动轨迹一个扫掠体Swept Volume并检查这条轨迹是否与任何标记为静态Static或运动学Kinematic的碰撞体相交。如果相交物理引擎会计算出精确的碰撞发生时间点并将刚体“推回”到那个位置然后处理碰撞事件。优点有效防止自身高速穿模对于高速运动的物体如玩家发射的炮弹、疾驰的赛车能确保它不会穿过静态的关卡墙壁或预设好路径的运动平台。性能开销可控因为它只针对静态和运动学碰撞体进行连续检测而这两种碰撞体在场景中通常是有限的所以性能开销比下一种模式要小。局限性与误区 这是最容易让人困惑的地方。Continuous模式不能防止该刚体被其他高速运动的刚体穿过也不能防止两个都设置了Continuous模式的刚体互相穿过。误区示例玩家Rigidbody A和敌人发射的子弹Rigidbody B都设置了Continuous模式。当子弹速度极快时它仍然有可能穿过玩家。因为对于子弹B来说玩家A既不是静态碰撞体也不是运动学刚体除非你特意把玩家设为Kinematic但这通常不对所以B不会对A进行连续检测。适用对象通常你应该给高速运动的投射物子弹、飞镖、玩家控制的角色尤其是第一人称/第三人称控制器或者高速移动的载具设置Continuous模式以保护它们不会撞进静态的关卡几何体中。注意事项运动学刚体Kinematic Rigidbody通常用于由代码如动画直接控制运动的物体比如移动的平台、升降梯。将它们设置为运动学并让高速物体使用Continuous模式可以确保可靠的碰撞。3.3 Continuous Dynamic连续动态检测最强的“互防”模式这是防御等级最高的模式旨在解决两个高速运动刚体之间的相互穿模问题。工作原理它不仅像Continuous模式一样会检测自身与静态/运动学碰撞体的连续碰撞还会检测自身与其他也启用了Continuous或Continuous Dynamic模式的刚体之间的连续碰撞。也就是说它为刚体之间提供了“双向”的连续碰撞检测保护。优点解决高速物体间的相互穿模这是它唯一且最重要的用途。例如在太空射击游戏中你和敌机都以极高速度相对飞行双方都使用Continuous Dynamic模式就能最大程度地避免“对穿”的尴尬情况。最全面的保护为刚体提供了最彻底的碰撞安全保障。致命缺点性能开销巨大这是三种模式中计算成本最高的。因为每一对使用此模式的刚体之间都需要进行昂贵的连续轨迹检测计算。如果一个场景中有大量比如几十个设置为Continuous Dynamic的物体物理性能会急剧下降导致帧率暴跌。使用需极度谨慎绝对不能滥用。通常只用于少数关键、且确实存在高速相互碰撞可能的物体上。如何选择Continuous Dynamic这是一个典型的性能与效果权衡的问题。你需要问自己“这两个物体都以极快的速度相对运动并且它们之间的碰撞是游戏玩法中至关重要的、必须被检测到的吗”典型用例玩家子弹 vs 敌人子弹在一些弹幕游戏中需要精确检测子弹间的相撞抵消。高速赛车游戏中的车辆碰撞赛车彼此间的碰撞需要非常精确即使速度很快。台球游戏中的开球瞬间白球以高速撞击三角形排列的球堆需要精确的第一时间碰撞检测。非典型用例应避免场景中所有飞舞的碎片。大量低速运动的NPC。玩家角色和所有敌人如果敌人不是高速冲撞型用Discrete或Continuous即可。踩坑实录我曾在一个弹幕射击原型中将屏幕上所有的子弹可能同时存在上百发都设为Continuous Dynamic结果在移动设备上帧率直接掉到20以下。后来优化为只有玩家子弹和少数几种大型敌弹使用此模式其他小型敌弹使用Discrete问题立刻解决。黄金法则按需分配能省则省。4. 组合策略与高级避坑技巧理解了单一模式我们更需要掌握如何在项目中组合使用它们。正确的策略不是“寻找一个万能模式”而是“为不同的物体分配合适的模式”。4.1 场景物体分类与模式配置表我们可以将场景中的物体大致分为几类并给出推荐的碰撞检测模式配置物体类型描述与示例推荐碰撞检测模式理由静态环境关卡地形、墙壁、不可移动的建筑。Collider勾选isTrigger为false。无Rigidbody 或Rigidbody设为IsKinematic它们是被碰撞的对象。不需要刚体或使用运动学刚体供其他物体进行连续检测。低速运动物体缓慢移动的平台、被推开的箱子、大部分行走的NPC。Discrete速度慢离散检测足够性能最优。中高速运动物体玩家角色、发射的炮弹、疾驰的赛车、快速移动的敌人。Continuous保护自身不穿过静态环境。这是最常用的“防穿模”设置。需精确互撞的高速物体对撞的赛车、相消的子弹、台球游戏中的球。Continuous Dynamic确保高速相对运动下的双方都能检测到碰撞。务必严格控制数量。传感器/触发器用于检测区域进入、拾取物品、检查点的碰撞体。Collider勾选isTrigger为true。Discrete(通常)触发器不产生物理反馈只发送消息。对于高速触发器有时也需要Continuous来确保触发但这属于OnTrigger事件范畴与物理碰撞响应不同。4.2 除了模式还有哪些因素导致穿模碰撞检测模式是主因但不是唯一原因。调整模式后问题依旧请检查以下方面物理时间步长Fixed Timestep在Edit - Project Settings - Time中Fixed Timestep默认是0.02s50次/秒。这个值越大物理更新越“慢”物体每步移动的距离就越长越容易穿模。对于高速游戏可以尝试适当减小这个值如0.01s但这会增加CPU负担因为物理更新更频繁了。碰撞体尺寸与形状尺寸过小一个尺寸为0.1 0.1 0.1的盒子碰撞体非常容易在离散检测中被跳过。确保碰撞体大小与视觉模型基本匹配。形状不匹配用一个简单的胶囊碰撞体去匹配一个复杂的人形模型在手臂、腿部等突出部位容易产生缝隙导致视觉上“蹭”到墙但物理上没检测到。可以考虑使用复合碰撞体多个简单碰撞体组合或网格碰撞体Mesh Collider性能开销大慎用。刚体插值InterpolationRigidbody组件上的Interpolation选项None, Interpolate, Extrapolate。这个选项是为了解决物理更新FixedUpdate和渲染更新Update不同步导致的物体抖动问题。它不会影响碰撞检测本身但能改善视觉平滑度。有时视觉上的“抖动”会被误认为是穿模。碰撞矩阵Layer Collision Matrix在Edit - Project Settings - Physics或Physics 2D中检查你物体所在的层Layer是否与目标物体的层取消了碰撞关系。如果根本没启用碰撞任何检测模式都无效。4.3 针对特定问题的实战配置案例案例一第一人称射击游戏中的子弹问题子弹速度极快经常穿过薄墙或敌人。解决方案子弹的Rigidbody碰撞检测模式设为Continuous。确保墙壁等静态障碍物的碰撞体不是触发器并且足够厚或在设计上避免使用极薄的单面墙体。如果子弹需要与其他高速子弹如敌弹相撞则将双方子弹都设为Continuous Dynamic但需评估数量对性能的影响。一个常见的替代方案是不使用真实的物理子弹而是用射线检测Raycast。在开枪瞬间从枪口发射一条射线命中哪里就立即产生命中效果。这完全避免了高速运动带来的穿模问题是FPS游戏的标配。此时刚体可能仅用于处理子弹下坠等模拟速度不必设得极高。案例二平台跳跃游戏中的玩家问题玩家从高速下落的平台边缘起跳有时会直接穿过平台底部。解决方案玩家角色Rigidbody碰撞检测模式设为Continuous。移动平台的Rigidbody设置为Kinematic运动学碰撞检测模式可以用Discrete因为它由代码控制移动每帧位置是确定的。这样玩家的Continuous检测就能对其生效。适当增加玩家脚部碰撞体的厚度如胶囊体的半径增加“检测面积”。案例三赛车游戏中的车辆问题车辆高速行驶时与其他车辆或护栏发生碰撞时感觉不真实有时会嵌入。解决方案玩家车辆和AI车辆Rigidbody碰撞检测模式均设为Continuous Dynamic。赛道护栏等静态物体确保有碰撞体。非常重要考虑使用车轮碰撞体WheelCollider而非普通的盒子/胶囊碰撞体来模拟车辆。WheelCollider是专门为车辆物理设计的它通过射线投射来检测地面和障碍本身就能更好地处理连续检测。可以尝试稍微减小Fixed Timestep让物理更新更频繁碰撞检测更细腻。5. 性能监控与调试工具正确地使用碰撞检测模式离不开有效的监控和调试。盲目使用Continuous Dynamic会导致性能灾难。5.1 如何监控物理性能Unity Profiler这是最强大的工具。打开Window - Analysis - Profiler在CPU使用率模块中重点关注Physics.Processing和Physics.Simulate所占用的时间。当你为大量物体启用Continuous Dynamic后会看到这些项的耗时显著上升。Stats面板在Game视图右上角点击Stats按钮。查看Physics部分的数值特别是Rigidbody的数量。数量激增通常意味着物理计算负担加重。5.2 可视化调试碰撞Gizmos显示在Scene视图中确保Gizmos开启。你可以在Edit - Project Settings - Physics中调整碰撞体的显示颜色方便查看。Debug.DrawLine / Debug.DrawRay在代码中使用这些方法可以在Game视图和Scene视图中绘制出射线、运动方向等帮助你直观理解物体的运动轨迹和碰撞检测范围。例如在FixedUpdate中绘制出刚体上一帧到这一帧的位移线可以清晰地看到离散检测的“跳跃”过程。自定义绘制扫掠体对于理解Continuous检测可以编写一个简单的编辑器脚本在OnDrawGizmos中计算出刚体在本帧的扫掠体如从上一帧位置到当前帧位置的胶囊体或盒子并用Gizmos绘制出来。这能让你亲眼看到连续检测所检查的“空间”。5.3 一个实用的性能测试方法当你对某个物体该用哪种模式存疑时可以做一个简单的A/B测试在场景中复制出该物体的多个实例比如20个。让它们以可能产生穿模的速度运动。在Profiler中记录一组使用Discrete模式时的物理耗时基准。将所有实例改为Continuous模式再次记录物理耗时。如果耗时增长在可接受范围内比如5%且穿模问题解决那么用Continuous是值得的。如果增长显著就需要考虑其他优化方案比如改变游戏设计降低速度、使用不同的碰撞体形状、或者改用射线检测等非物理方案。6. 常见问题排查清单QA这里汇总了在实际开发中最常遇到的一些困惑和问题你可以像查字典一样快速定位。Q1我给玩家和敌人都设置了Continuous为什么子弹还是能穿过敌人A这是最常见的误解。Continuous模式只保护该刚体不穿过静态/运动学物体。子弹刚体B穿过敌人刚体A对于子弹B来说敌人A不属于上述两类所以不进行连续检测。解决方案要么将子弹设为Continuous Dynamic如果敌人也是Continuous或Continuous Dynamic要么考虑使用射线检测来判定子弹命中。Q2两个都设置了Continuous Dynamic的物体为什么偶尔还是会穿模AContinuous Dynamic是计算开销最大的近似解决方案但并非完美。在极端情况下如速度极高或物体极薄仍有可能发生穿模。此外检查Fixed Timestep是否设置得过大以及碰撞体形状是否与视觉模型严重不符。Q3使用了Continuous模式性能下降很明显怎么办A首先用Profiler确认是否是物理开销增大。然后减少使用范围确保只有真正高速的物体在用。优化碰撞体用简单的原型碰撞体球、盒、胶囊代替复杂的网格碰撞体。调整层级碰撞矩阵让不必要的物体层之间不发生碰撞减少检测对。考虑替代方案对于子弹改用射线对于需要精准检测的区域使用触发器配合代码进行更粗粒度的检测。Q4运动学刚体Kinematic应该用什么碰撞检测模式A运动学刚体的运动完全由脚本如Transform.position控制物理引擎不计算它的速度。因此对于其他需要检测与它碰撞的刚体来说它被视为一个“静态”的障碍物。运动学刚体自身的碰撞检测模式通常保持为Discrete即可因为它不主动进行物理运动。关键是要与它碰撞的其他刚体如玩家需要设置为Continuous或Continuous Dynamic。Q5触发器isTrigger的碰撞检测受模式影响吗A受影响但逻辑不同。触发器不产生物理碰撞反应只发送OnTriggerEnter/Stay/Exit消息。对于高速运动的触发器如果使用Discrete模式也可能错过触发事件。如果你需要确保一个高速运动的触发器比如一个高速通过的奖励区域能被可靠触发可以将其刚体的碰撞检测模式也设为Continuous。但请注意这触发的是OnTrigger...事件而非OnCollision...事件。Q62D物理Rigidbody2D有类似的设置吗A有但选项不同。Rigidbody2D的Collision Detection属性有Discrete和Continuous两种模式其含义与3D中的Discrete和Continuous类似。但没有单独的Continuous Dynamic模式。在2D中Continuous模式会尝试防止该刚体与其他所有刚体包括动态刚体的穿模其行为更接近于3D中的Continuous Dynamic但实现原理和开销有所不同需要根据实际测试来评估。处理物理穿模问题本质上是在模拟精度和运行性能之间寻找最佳平衡点。没有一劳永逸的银弹最好的策略就是深入理解引擎提供给你的工具——Discrete, Continuous, Continuous Dynamic这三种模式——然后像一位精明的项目经理一样根据每个游戏对象在项目中的“重要性”和“行为特点”为它们分配合适的“资源”即碰撞检测模式。记住一个简单的决策流低速物体用Discrete需要防撞墙的高速物体用Continuous只有那些必须进行高速互撞的关键物体才值得动用Continuous Dynamic这把“牛刀”。在项目后期进行全面的物理性能剖析往往能发现一些可以优化回Discrete模式的物体这能为你的游戏赢得宝贵的性能空间。