引言:碰撞体,UE5 里最容易被低估的“隐形杀手”
如果你问一个刚接触 UE5 的学员,什么是最容易让他崩溃的系统?十有八九不是蓝图,不是材质,而是那个看不见摸不着、却无处不在的 碰撞体(Collision)。它就像房间里的空气——平时感觉不到,一旦出了问题,你连门都出不去。作为在火星人教育带了十年 UE5 课程的老兵,我见过太多学员在碰撞体上栽跟头:角色卡进地板、子弹穿透墙壁、载具原地起飞、性能断崖下跌……每一个案例背后,都对应着一个或几个典型的“坑”。今天,我就把这些年踩过的坑、学员掉过的坑,一次性给你排干净。这篇文章不追求面面俱到,只聚焦于实战中最容易翻车的 7 个坑,每个坑都遵循“现象→根因→解决方案→预防措施”的路径,把我当年的血泪教训,变成你的避坑指南。
坑 1:胶囊体 VS 盒体——选错碰撞形状,角色秒变“幽灵”
现象:你给角色添加了碰撞体,但角色在场景中行走时,明明没有碰到任何东西,却会莫名其妙地卡住、抖动,甚至穿过地面。或者反过来,角色能直接穿墙而过,像个幽灵。
根因:绝大多数情况下,这是因为你用了错误的碰撞形状。胶囊体(Capsule)是 UE5 中角色移动组件默认的碰撞形状,它最适合模拟人形角色的轮廓——圆滑、无棱角,能平滑地滑过墙壁和障碍物。而盒体(Box)则是方方正正的,当你用盒体作为角色碰撞时,任何微小的凸起或墙面接缝都会导致角色被“绊住”,产生抖动。反之,如果你用了一个过于简化的碰撞形状(比如一个极小的球体)去代替角色,那么角色就会“缩”进墙体,造成穿模。
解决方案:对于人形角色,永远使用胶囊体作为根碰撞体(Root Collision),并且匹配好半径和半高,让胶囊体尽可能贴合角色模型,但不要完全包裹住模型(留出几厘米的余量,避免视觉穿模)。对于场景中的静态物体,如墙壁、地板、箱子,使用盒体或凸包(Convex Hull)即可,但要注意凸包的顶点数,过多会导致性能问题。
预防措施:在项目初期,就建立一个“碰撞形状规范”:角色一律用胶囊体,可交互物体用盒体或简单凸包,复杂静态网格体(如岩石、柱子)用“简单碰撞(Simple Collision)”自动生成,并手动调整到最简形状。记住:碰撞体的目的是“模拟”,不是“精确复制”。
技巧提示:在静态网格体编辑器中,你可以使用“Collision → Auto Convex Collision”一键生成凸包碰撞,但记得设置“Max Hull Verts”和“Max Hulls”,控制碰撞精度和性能的平衡。
坑 2:碰撞预设(Collision Preset)——所有物体都是“Block All”的灾难
现象:场景中所有物体都设置了“Block All”碰撞预设,结果角色走路像在泥潭里,子弹打不出去,交互按钮点不到,更可怕的是,性能帧率掉到个位数。
根因:碰撞预设(Collision Preset)决定了这个物体与哪些对象产生碰撞、重叠或忽略。新手最容易犯的错误就是图省事,把所有物体都设为“Block All”。这会导致:1)角色与地面、墙壁、道具、NPC 全都进行碰撞检测,物理引擎需要计算海量的碰撞对,性能急剧下降;2)很多本应“可穿透”的物体(比如烟雾、粒子、触发区域)也变成了实体,破坏了游戏逻辑。
解决方案:学会使用 UE5 的碰撞通道(Collision Channel)和预设。在项目设置中,你可以自定义碰撞通道,比如“WorldStatic”、“Pawn”、“Character”、“Projectile”等。然后为每个物体选择最合适的预设:静态物体用“WorldStatic”,角色用“Pawn”,子弹用“Projectile”并设置为“Overlap”或“Block”特定通道。你要明确每种物体的“角色”和“职责”,而不是一刀切。
预防措施:在项目开始前,花半天时间规划好碰撞通道表(Collision Channel Matrix),明确哪些物体相互碰撞、哪些重叠、哪些忽略。这个表一旦定好,后续所有资产的碰撞设置都严格按表执行。我的经验是:能用“Overlap”实现的交互,绝不用“Block”。比如拾取物、触发区域、伤害区域,统统用 Overlap。
注意:碰撞通道不是越多越好,每增加一个通道,碰撞检测的矩阵就会指数级扩大,性能开销也随之增加。建议控制在 6-8 个以内。
坑 3:碰撞复杂度(Collision Complexity)——高模碰撞体,性能的隐形黑洞
现象:你的场景里放了几十把精致的椅子、几面雕花墙壁,帧率瞬间从 60 掉到 20,但你的模型面数其实不高。
根因:UE5 的碰撞检测是基于物理形状的,而不是基于渲染网格体。如果你没有为静态网格体指定独立的碰撞体,引擎会默认使用渲染网格体本身作为碰撞(即“Use Complex Collision as Simple”),这会导致碰撞体的三角形数量与渲染网格体一样多,物理引擎每帧都要对这些三角形进行碰撞检测,性能自然崩溃。
解决方案:为每个静态网格体在编辑器里生成“简单碰撞”形状,通常是盒体、球体、胶囊体或凸包的组合。对于复杂物体,可以用多个简单碰撞体组合来近似。在网格体编辑器的“Collision”菜单中,选择“Auto Convex Collision”或手动添加球体、盒体等,并确保“Collision Complexity”设置为“Use Simple Collision as Complex”,这样物理引擎只计算简单的碰撞形状。
预防措施:养成习惯,任何静态网格体导入后,第一件事就是检查碰撞设置。在内容浏览器中,你可以批量选中多个网格体,右键选择“Collision → Auto Convex Collision”批量生成简单碰撞。记住:碰撞体是“包装”,不是“模型”。
| 碰撞复杂度类型 | 性能开销 | 适用场景 |
|---|---|---|
| Simple Collision(简单碰撞) | 低(几个-几十个三角形) | 大部分静态物体、角色、可交互物体 |
| Complex Collision(复杂碰撞) | 高(数千-数万三角形) | 地形、需要精确射击的墙壁(但需谨慎) |
| Mixed(混合) | 中等 | 可同时使用简单和复杂碰撞的物体 |
性能警告:切勿在运行时动态修改碰撞形状或频繁改变碰撞预设,这会导致物理引擎重建碰撞树,造成卡顿。
坑 4:碰撞与移动组件——角色卡顿的元凶,根因在“更新碰撞”
现象:角色在移动时,偶尔会卡顿一下,或者被某个不可见的物体挡住,即使那个物体看起来已经移开了。
根因:这个问题往往出在移动组件(CharacterMovementComponent)的碰撞更新机制上。UE5 的角色移动组件默认会在每次移动时进行碰撞检测,但如果你在蓝图中频繁修改了角色的碰撞形状或碰撞预设,或者你在移动过程中动态改变了角色的胶囊体大小(比如蹲下),会导致碰撞体与移动不同步,产生“幽灵碰撞”——碰撞体已经变了,但物理引擎还在使用旧的碰撞数据。
解决方案:在修改碰撞体后,调用 UpdateCollisionProfile() 或 SetCapsuleSize() 后,需要调用 UpdateNavAgent() 或手动触发 MoveUpdatedComponent() 来强制物理引擎刷新。更稳妥的做法是,将碰撞体的修改放在 BeginPlay 中完成,而不是在 Tick 中。对于蹲下等动作,使用角色移动组件提供的“Crouch”功能,它会自动处理胶囊体缩放和碰撞更新。
预防措施:尽量避免在运行时修改碰撞体大小或预设,如果必须修改,确保修改后立即调用 UpdateCollisionProfile,并在下一帧前不要执行任何移动操作。另外,在移动组件中勾选“Sweep”选项,让移动时进行扫掠检测,可以避免碰撞体“卡”进缝隙。
技巧提示:如果你发现角色在斜坡上滑行异常,检查移动组件中的“Walkable Floor Angle”设置,默认是 44.76 度,如果你的斜坡角度大于这个值,角色就会打滑。
坑 5:碰撞与物理模拟——物体“穿模”和“爆炸”的真相
现象:你模拟一个箱子,把它放到桌子上,结果箱子要么直接穿过桌面掉到地上,要么在接触时“爆炸”飞得到处都是。
根因:这通常是因为物理模拟(Simulate Physics)和碰撞设置不匹配。模拟物理的物体必须具有“Simulate Physics”开启,并且其碰撞体必须是“Block”类型,而不是“Overlap”。如果碰撞体是 Overlap,物理引擎就不会处理碰撞,物体会直接穿过。而“爆炸”通常是因为碰撞体过于复杂(比如高模凸包),导致物理引擎在接触时产生巨大的碰撞力,或者因为碰撞体的初始位置与另一个物体重叠,导致物理引擎强制分离。
解决方案:确保模拟物理的物体使用“Simple Collision”,并且碰撞预设为“BlockAllDynamic”或类似。在放置物体时,确保它没有与任何其他物体重叠。如果物体仍然爆炸,可以降低其“Linear Damping”和“Angular Damping”值,或者增加“Max Depenetration Velocity”和“Penetration Depth”的容差。在项目设置中,你可以调整“Physics”的“Solver Iterations”,增加迭代次数可以更稳定,但会增加性能开销。
预防措施:为模拟物理的物体创建一个专门的碰撞通道,比如“PhysicsBody”,并确保它只与“WorldStatic”和“PhysicsBody”通道碰撞。同时,在放置模拟物理物体时,使用“Snap to Floor”或手动微调,避免初始重叠。
注意:不要给模拟物理的物体使用“Convex Collision”且顶点数过多(超过 16 个),否则物理引擎的 GJK 算法会变得非常慢,且容易产生不稳定的接触。
坑 6:碰撞与射线检测(LineTrace)——为什么你的子弹总是“打不中”
现象:你写了一个射线检测用于射击,但子弹有时候能打中目标,有时候却直接穿过,或者打在了空气上。
根因:射线检测的“命中”取决于被检测物体的碰撞通道和响应。如果你在射线检测中指定了“Visibility”或“Camera”通道,但目标物体的碰撞预设没有对这些通道做出“Block”响应,射线就会穿过。另一个常见问题是,你使用了“Trace by Channel”而物体被设置为“Ignore”该通道。此外,如果你对角色进行射线检测,角色的胶囊体是“Pawn”通道,但你的射线只检测“WorldStatic”,那么即使角色站在你面前,你也打不中他。
解决方案:明确你的射线检测需要检测哪些对象,然后在射线检测函数中正确指定通道和对象类型。例如,射击敌人应该使用“Trace by Object Type”,并勾选“Pawn”和“PhysicsBody”,而不是只使用默认的“Visibility”。同时,确保目标物体的碰撞预设对相应通道有“Block”响应。
预防措施:在项目设置中,为射线检测创建专用的碰撞通道,如“Interaction”、“Projectile”、“Visibility”,并在碰撞矩阵中设置好各物体对这些通道的响应。这样,射线检测只需要指定一个通道,就能精准命中所有该响应的物体。
// 在蓝图中使用“Line Trace by Channel”时,选择“Visibility”通道,并确保目标物体对“Visibility”通道为“Block”。
技巧提示:如果你需要检测多个不同类型的物体,使用“Multi Line Trace by Object Type”,并传入一个对象类型数组,这样一次射线就能检测所有指定类型。
坑 7:碰撞与性能——别让碰撞体成为你项目的“帧率杀手”
现象:你的场景看起来很精致,但帧率始终上不去,尤其是在大场景中,移动视角时明显卡顿。
根因:碰撞体数量过多、碰撞体过于复杂、以及碰撞检测的频率过高。UE5 的物理引擎会为每个碰撞体创建一个“碰撞代理”,并在每一帧进行碰撞对检测(Broadphase 和 Narrowphase)。如果你的场景里有上千个物体,每个物体都有复杂的凸包碰撞,物理引擎的计算量会非常巨大。更隐蔽的是,很多物体虽然不参与物理模拟,但它们的碰撞体仍然会参与碰撞检测,增加了开销。
解决方案:使用“碰撞体实例化”和“碰撞体合并”。对于静态物体,可以将它们的碰撞体合并为一个大的凸包或盒体,减少碰撞体的数量。在 UE5 中,你可以使用“Merge Actors”工具将多个静态网格体合并为一个,并自动生成一个简单的碰撞体。对于动态物体,尽量减少同时参与物理模拟的数量,并设置“Sleep”状态,让不运动的物体进入睡眠,减少计算。
预防措施:定期使用“Collision”视图模式(Alt+C)检查场景中的碰撞体,看看是否有不必要的碰撞体。在项目设置中,调整“Physics”的“Max Contact Offset”,增大这个值可以让物体在接触前就进行碰撞,但也会增加计算量。建议保持默认。
性能建议:在大型开放世界中,使用“World Partition”和“HLOD”来减少同时加载的碰撞体数量。对于远处物体,可以将其碰撞体简化为一个球体或直接禁用碰撞。
结语:碰撞体是门手艺,不是玄学
以上 7 个坑,是我和我的学员们在实战中用无数个加班的夜晚换来的经验。碰撞体看似简单,但它的设计直接影响到游戏的玩法、性能和稳定性。记住:碰撞体不是“物理的真实”,而是“游戏性的妥协”。你要做的,是在精度和性能之间找到那个平衡点。希望这篇避坑指南能让你少走弯路,把更多时间花在创造有趣的世界,而不是和看不见的碰撞体搏斗。如果你在项目中遇到了其他奇葩的碰撞问题,欢迎在评论区交流,我会一一解答。
(本文为火星人教育原创技术教程,如需转载请联系授权。)

评论(0)