第一次打开UE4编辑器时,看到场景中那些半透明的绿色线框,我完全不明白它们的作用。直到角色莫名其妙卡在台阶上,或者穿墙而过时,才意识到这些就是碰撞体(Collision)。简单来说,碰撞体决定了游戏世界中物体的物理边界 - 哪里能走、哪里会被挡住、什么能捡起来。
在静态网格体(Static Mesh)编辑器中,点击工具栏的"碰撞(Collision)"按钮,就能看到当前模型的碰撞体积。UE4提供了几种基础碰撞体生成方式:
cpp复制// 通过代码添加盒体碰撞的示例
UBoxComponent* BoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
BoxCollision->SetupAttachment(RootComponent);
BoxCollision->SetBoxExtent(FVector(50,50,50));
实际项目中,自动生成的碰撞往往不符合预期。比如一个复杂的雕塑模型,用10个定制盒体拼成的碰撞体,比自动生成的32面凸包碰撞体性能更好、更精准。记住:能用简单碰撞体就别用复杂的。
就像现实世界中的物质分类,UE4的碰撞系统首先需要明确"你是谁"。在碰撞组件细节面板中,Object Type定义了当前物体的本质属性:
我曾在一个赛车游戏中犯过错 - 把赛道护栏设为WorldDynamic而不是Vehicle,结果车辆撞上去直接穿模。不同类型的物体间交互规则完全不同。
确定了"你是谁",还要定义"你如何对待他人"。碰撞响应有三种基本模式:
| 响应类型 | 物理模拟 | 射线检测 | 典型应用场景 |
|---|---|---|---|
| Block | ✔️ | ✔️ | 实心墙体 |
| Overlap | ✖️ | ✔️ | 触发器区域 |
| Ignore | ✖️ | ✖️ | 特效粒子 |
在蓝图编辑器中,可以通过SetCollisionResponseToChannel节点动态修改响应。比如实现"穿墙作弊模式":
cpp复制// 关闭与墙壁的碰撞
CharacterMesh->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Ignore);
当两个设置为Block的物体相撞时,就会触发Hit事件。但要注意两个必要条件:
在第三人称模板中,子弹击中墙壁的火花效果就是典型应用。我常用Hit事件做这些功能:
cpp复制// 在Actor蓝图中的Hit事件处理
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
UPrimitiveComponent* OtherComp, FVector NormalImpulse,
const FHitResult& Hit)
{
if(OtherActor->ActorHasTag("Enemy")){
float Damage = NormalImpulse.Size() / 1000;
OtherActor->TakeDamage(Damage, FDamageEvent(), nullptr, this);
}
}
Overlap更像是一种"感应",不需要物理接触。比如角色走进宝箱触发范围时,出现"按E拾取"提示。常见应用场景:
新手容易忽略的是:Overlap事件需要双方至少有一方设置为Overlap。我曾花两小时debug一个不触发的Overlap事件,最后发现是双方都设成了Block。
cpp复制// 蓝图中的Overlap事件典型用法
Begin Overlap Event -> Cast To PlayerCharacter -> Show Interaction Widget
与其每次都手动配置各通道响应,不如使用预设。UE4提供了多种预设模板:
自定义预设时,建议复制现有预设再修改。比如需要一扇可以被子弹击穿但阻挡角色的门:
当默认通道不够用时,可以创建专属通道。比如做一个只有特定武器能破坏的护盾:
cpp复制// 射线检测指定自定义通道
FCollisionQueryParams Params;
Params.AddIgnoredActor(GetOwner());
GetWorld()->LineTraceSingleByChannel(HitResult, Start, End,
ECC_GameTraceChannel1, Params);
不当的碰撞设置会导致严重性能问题。几个实测有效的优化技巧:
在开放世界项目中,我通过将200米外的建筑碰撞设为Query Only,帧率提升了15%。记住:碰撞计算是物理线程的主要负担。
结合前面所有知识点,我们实现一个完整的可破坏墙体:
碰撞设置:
蓝图逻辑:
cpp复制Event Hit ->
检查攻击者是否有"Hammer"标签 ->
应用径向力 ->
播放破碎音效 ->
延迟2秒后销毁Actor
这种设计既符合物理直觉,又提供了充足的游戏性。关键在于平衡真实感和游戏体验 - 完全真实的破坏计算反而可能让玩家感到挫败。