引言:碰撞体,UE5里最容易被低估的‘隐形杀手’
如果你觉得碰撞体(Collision)就是把盒体(Box)、球体(Sphere)、胶囊体(Capsule)拖到模型上,然后祈祷它别穿模——那你迟早会在项目后期付出代价。我在火星人教育带了8届UE5学员,见过太多项目在临交付前因为碰撞问题崩盘:角色卡进楼梯、子弹穿过墙壁、载具在平地上抖动、物理模拟物体莫名爆炸……这些‘灵异事件’背后,90%都是碰撞体设置埋下的雷。
今天,我不打算按手册给你讲一遍Collision的每个参数,那太无趣了。我要用7个血泪教训,带你绕过那些连资深开发者都会踩的坑。每个坑我都会告诉你:现象是什么、根因在哪、怎么解决、以及如何预防。准备好,这可能是你今年读过最‘疼’的一篇UE5教程。

坑1:碰撞体与网格不匹配——‘穿模’的根源
现象
你把一个精美的雕像模型放进场景,玩家走过去,明明离雕像还有半米,却被空气墙挡住;或者反过来,玩家可以‘穿透’雕像的裙摆,因为碰撞体只覆盖了躯干。更糟的是,子弹打在雕像的镂空花纹上,却像打在实心铁块上——因为碰撞体是简单的盒体。
根因
默认情况下,UE5会自动为静态网格体(Static Mesh)生成简单碰撞(Simple Collision),通常是盒体或球体。这种碰撞体只关心‘大概范围’,完全不理会模型的真实几何细节。美术同学精心雕刻的每一道凹槽、每一个镂空,在物理引擎眼里就是一块实心砖。
解决方案
为复杂模型使用复杂碰撞(Complex Collision),即直接使用网格体的三角面作为碰撞。在静态网格体编辑器中,勾选Collision Complexity为Use Complex Collision as Simple。但注意,这会显著增加物理计算开销。更优的方案是:为模型手动生成多个凸包(Convex Hull)组合,用十几个凸包去‘包裹’模型,既接近真实形状,又保持性能。
// 在蓝图或C++中设置复杂碰撞示例(C++)
UStaticMeshComponent* MeshComp = CreateDefaultSubobject(TEXT("Mesh"));
MeshComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComp->SetCollisionObjectType(ECC_WorldStatic);
MeshComp->SetCollisionResponseToAllChannels(ECR_Block);
// 注意:复杂碰撞作为简单碰撞时,物理模拟开销较大,慎用于动态物体
预防措施
在项目初期就制定碰撞规范:静态环境用简单碰撞+手动凸包,动态可交互物体用精确碰撞,但限制数量。并利用UE5的Collision Viewer(编辑器中按‘C’键)实时检查碰撞体形状。
技巧:使用‘Collision Analyzer’(碰撞分析器)窗口,可以录制并分析物理交互,快速定位异常碰撞。
坑2:碰撞预设(Collision Preset)滥用——‘一切皆阻挡’的灾难
现象
项目里所有物体都用了默认的‘Block All’预设,结果:玩家的子弹打不碎玻璃(因为玻璃阻挡一切),敌人AI无法穿过半掩体(因为掩体阻挡视线和移动),甚至玩家自己的脚步声都触发不了触发器(因为触发器被阻挡了)。
根因
碰撞预设(Collision Preset)是一组对各类物体(WorldStatic, Pawn, PhysicsBody等)的响应规则(阻挡/重叠/忽略)。‘Block All’意味着对所有物体都设为阻挡,这导致任何交互都必须穿过‘阻挡’的过滤,很多逻辑被意外拦截。
解决方案
根据物体语义选择合适的预设:静态环境(WorldStatic)默认‘Block All’没问题,但可交互物体(如门、箱子)应使用‘Block All Dynamic’或自定义预设;触发区域(Trigger)应设为‘Overlap All’;投射物(Projectile)应设为‘Block Pawn, Overlap Static’等。自定义预设时,明确每个通道的响应。
| 预设名称 | 适用场景 | 常用通道响应 |
|---|---|---|
| BlockAll | 墙壁、地面 | 所有通道阻挡 |
| BlockAllDynamic | 动态障碍物 | 阻挡Pawn、PhysicsBody,忽略WorldStatic |
| OverlapAll | 触发区域 | 所有通道重叠 |
| IgnoreOnlyPawn | 装饰物 | 忽略Pawn,其余阻挡 |
预防措施
项目启动时,创建一套自定义碰撞通道(Custom Channels),例如:Projectile, Interactable, Vision, Camera等。并为每种物体类型定义好预设,写进团队规范文档。
注意:修改碰撞预设后,务必在游戏中测试,因为有些响应组合会导致性能问题(例如大量重叠查询)。
坑3:忽略碰撞通道(Collision Channel)——‘看不见’的碰撞
现象
你明明给角色加了胶囊体碰撞,但角色却从墙上穿过去;或者射线检测(LineTrace)总是检测不到某些物体,导致交互失效。
根因
碰撞通道(Collision Channel)是UE5物理系统的核心,它决定了物体属于哪一类(Object Type),以及它与其他类别的响应。很多初学者只设置了碰撞预设,却忽略了自定义通道的划分,导致默认通道(WorldStatic, Pawn等)无法满足需求。例如,你想让子弹只打中敌人,不打中玩家,但两者都属于Pawn通道,于是子弹对Pawn的响应是‘阻挡’,结果打中谁都是阻挡,无法区分。
解决方案
在Project Settings中,添加自定义对象通道(例如:Enemy, Player, Projectile),并设置它们之间的碰撞响应。然后,在物体的碰撞预设中,将Object Type设为自定义通道,并调整响应。例如:子弹设为Projectile通道,对Enemy设为Block,对Player设为Ignore,对WorldStatic设为Block。
// 在C++中设置自定义通道示例
#define ECC_Projectile ECC_GameTraceChannel1
#define ECC_Enemy ECC_GameTraceChannel2
// 然后可以在碰撞预设中引用这些通道
预防措施
在项目初期,规划好所有需要的通道,避免后期频繁修改。在蓝图中,使用Collision Profile时,注意选择正确的Object Type。
技巧:使用‘Collision Channel’的‘Visibility’和‘Camera’通道,可以优化投线检测性能。
坑4:动态物体碰撞体过多——性能杀手
现象
场景中摆放了1000个带有碰撞体的碎片物体,每个都使用复杂碰撞。游戏帧率从60fps骤降到20fps,物理引擎每帧都在进行海量的碰撞计算。
根因
物理引擎的碰撞检测复杂度与碰撞体的数量、类型(凸包/三角网格)成正比。复杂碰撞(三角网格)的计算成本远高于简单碰撞(盒体/球体)。当动态物体(如可拾取的碎片)数量庞大时,每帧都要进行Broadphase(粗测)和Narrowphase(精测),性能急剧下降。
解决方案
1. 对于大量动态物体,使用简单碰撞(盒体/球体),不要使用复杂碰撞。2. 使用碰撞体合并(Collision Merging),将多个相邻物体的碰撞体合并为一个,减少碰撞体数量。3. 对于非交互的装饰物,可以禁用碰撞(Collision Enabled = No Collision)。4. 利用物理资产(Physics Asset)的LOD,为不同距离的物体使用不同精度的碰撞体。
预防措施
在项目初期,使用Profiler监控物理耗时,设定碰撞体数量上限。对于大规模场景,使用Hierarchical Instanced Static Meshes (HISM),它支持合并碰撞体,大幅降低开销。
注意:HISM的碰撞体是合并的,但物理模拟时,每个实例仍可独立响应,只是碰撞检测更高效。
坑5:忽略碰撞体的物理材质(Physical Material)——‘手感’不对
现象
角色走在金属板路上,脚步声却是沉闷的‘咚咚’声,像踩在棉花上;子弹打在石墙上,却没有反弹和火星四溅的效果;载具在冰面上行驶,却没有打滑的感觉。
根因
碰撞体默认使用物理材质(Physical Material)中的默认值(Friction=0.7, Restitution=0.3)。不同表面(金属、混凝土、冰)需要不同的摩擦力和弹性,以及不同的音效、特效。忽略物理材质,所有表面都一个手感,游戏体验大打折扣。
解决方案
为每种表面创建物理材质资产,设置合适的Friction(摩擦力)和Restitution(弹性)。在静态网格体或碰撞体上指定该物理材质。同时,可以在物理材质中设置表面类型(Surface Type),用于触发音效和特效(如脚步声、弹痕)。
// 创建物理材质并指定给碰撞体的示例(C++)
UPhysicalMaterial* PhysMat = LoadObject<UPhysicalMaterial>(nullptr, TEXT("/Game/Physics/MetalPhysMat.MetalPhysMat"));
MeshComp->SetPhysMaterialOverride(PhysMat);
预防措施
在项目初期,建立物理材质库,并规范命名(如PM_Metal, PM_Concrete)。在场景中,使用Landscape的物理材质图层(Layer)来区分不同地表区域。
技巧:利用物理材质的‘Friction Combine Mode’和‘Restitution Combine Mode’来控制多个材质碰撞时的混合方式。
坑6:碰撞体与动画不同步——角色‘穿模’的另一种原因
现象
角色在播放攀爬动画时,身体明明已经扒到墙沿,但碰撞体还停留在原地,导致角色要么悬空,要么被弹开。或者,角色在翻滚时,碰撞体没有跟随动画变形,导致角色卡进障碍物。
根因
角色的碰撞体(通常是胶囊体)是独立于骨骼网格体的组件,它不会自动跟随动画的骨骼运动。如果动画中角色重心大幅移动,而碰撞体没有同步,就会产生穿模或浮空。
解决方案
1. 使用Root Motion驱动角色移动,让碰撞体跟随动画根骨骼移动。2. 在动画蓝图中,根据动画状态动态调整胶囊体的位置和大小(例如,蹲伏时降低胶囊体高度)。3. 对于复杂交互(如攀爬),使用Motion Warping或Animation Montage配合碰撞查询,使碰撞体贴合动画。
预防措施
在制作角色动画时,与程序沟通好碰撞体的变化需求。在动画蓝图中,使用On Montage Started和On Montage Ended事件来调整碰撞体。
注意:动态调整胶囊体时,要确保物理模拟处于合适状态,避免产生不必要的弹跳。
坑7:碰撞检测的‘时序’问题——物理子步(Substep)的陷阱
现象
你发射一颗高速子弹(速度5000m/s),但子弹却穿过了薄墙,没有触发碰撞。或者,两个快速移动的物体,明明应该相撞,却互相穿过,像幽灵一样。
根因
UE5的物理引擎默认以固定时间步长(如60Hz)进行碰撞检测。如果物体移动速度过快,在单个步长内可能从碰撞体的一侧完全穿越到另一侧,导致碰撞检测遗漏。这被称为‘隧穿效应’(Tunneling)。
解决方案
1. 对于高速物体,启用Continuous Collision Detection (CCD),它会进行更精细的扫掠检测(Sweep),防止隧穿。2. 调整物理子步(Substep)的数量,增加每帧的物理计算次数。3. 对于子弹等投射物,使用LineTrace代替物理碰撞体,每帧检测射线与场景的交点。
// 启用CCD的示例(C++)
MeshComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComp->SetUseCCD(true); // 开启CCD
预防措施
在项目设置中,调整Physics的Substep参数(默认为1,可增加至2或3),但注意性能开销。对于关键高速物体,务必开启CCD。
技巧:CCD对性能有影响,只在必要物体上开启,不要全局开启。
实战案例:一个完整的碰撞体设置流程
为了让你更直观地理解,我结合一个常见的‘可破坏掩体’系统,演示正确的碰撞体设置流程。这个系统在射击游戏中非常常见,也是很多学员容易出错的点。
步骤1:创建自定义碰撞通道
在Project Settings → Engine → Collision中,添加两个通道:Destructible和Bullet。设置Destructible对Bullet为Block,对WorldStatic为Overlap(因为掩体可能放在地上,但不需要阻挡地面)。
步骤2:创建物理资产
为掩体模型创建物理资产(Physics Asset),手动添加多个凸包(Convex Hull)来包裹模型的主要结构,避免使用复杂碰撞。
步骤3:设置碰撞预设
在静态网格体编辑器中,新建碰撞预设,Object Type设为Destructible,Collision Responses里,对Bullet设为Block,对Pawn设为Block(防止玩家穿过),对WorldStatic设为Overlap(允许与地面重叠)。
步骤4:处理子弹
子弹的碰撞预设设为:Object Type为Bullet,对Destructible为Block,对WorldStatic为Block,对Pawn为Ignore。开启CCD,并设置合适的物理材质(高弹性,以便反弹)。
步骤5:测试与优化
在编辑器中模拟,使用Collision Analyzer检查子弹是否稳定触发掩体破坏。调整凸包数量,确保性能。
通过这个流程,你避免了坑1(碰撞体不匹配)、坑2(预设滥用)、坑3(通道混乱)、坑5(材质不对)、坑7(隧穿),并部分解决了坑4(性能)和坑6(动画同步)。
行业案例:AAA项目中的碰撞体哲学
在《堡垒之夜》和《战争机器》这类大型项目中,碰撞体设置是物理团队的核心工作之一。他们有一套严格的碰撞体分级:视觉碰撞(Visual Collision)用于精确交互,简单碰撞(Simple Collision)用于环境大形,触发器(Trigger)用于逻辑区域。他们甚至为每个角色制作了多套碰撞体,以适配不同的动画状态。
例如,在《战争机器》的掩体系统中,掩体的碰撞体是经过精心设计的凸包组合,既能抵挡子弹,又允许玩家贴墙移动。而子弹的碰撞体则使用CCD,确保高速下不穿模。这些经验,正是你在项目中需要积累的。
记住:碰撞体不是物理系统的附属品,而是游戏体验的骨架。一个完美的碰撞体设置,应该让玩家感觉‘物理就是真实’。
结语:碰撞体是门手艺,不是玄学
这7个坑,每一个都是我或我的学员用无数个加班夜换来的教训。碰撞体设置看似简单,实则暗藏玄机。它需要你对物理引擎的底层机制有清晰理解,更需要你在项目初期就建立规范和流程。希望这篇避坑指南能让你少走弯路,把时间花在真正有价值的创造上。如果你在项目中遇到了更奇葩的碰撞问题,欢迎来火星人教育找我,我们课上见。








评论(0)