UE4开启SkeletalMesh三角面碰撞失败(EnableperpolyCollision无效)

来源:互联网 发布:奔驰诊断软件下载 编辑:程序博客网 时间:2024/05/18 13:07

解决方案:不要在角色蓝图里的SkeletalMeshComponent里面勾选EnableperpolyCollision,要找到SkeletalMesh资源蓝图,在资源蓝图里面勾选EnableperpolyCollision。(在UE4官方论坛也有人问过)

分析:这可能是UE引擎里面的一个Bug。为了完全弄清这个Bug,我特意跟踪了一下代码,想深入了解原因的可以继续往下看。
首先要知道,开启一个三角面的复杂碰撞需要经过一个物理Cook过程,这个过程就是将SkeletalMesh的渲染数据(三角面顶点信息)保存,然后Physics引擎根据这些顶点来计算出一个复杂的物理碰撞体。
这个Cook后的信息同时与他的对应平台会作为一个结构体保存在BodySetup的CookedFormatData数组里面,但是这个数组里面指向Cook的指针可能为空(如果对物理BodySetup等信息不了解,建议先看看这篇文档 UE4物理模块分析)。

CookedFormatDataFormatName:CookedDataPointer:

那问题就出在这个BodySetUp上面,SkeletalMeshComponent与SkeletalMesh都有一个BodySetup成员,当我们在角色蓝图里面勾选SkeletalMeshComponent的EnableperpolyCollision时。他会获取SkeletalMesh的BodySetup的CookedFormatData来判断当前是否有Cook数据,如果有的话就会跳过Cook过程。

void USkeletalMeshComponent::OnCreatePhysicsState(){ // UE_LOG(LogSkeletalMesh, Warning, TEXT("Creating Physics State (%s : %s)"), *GetNameSafe(GetOuter()),  *GetName()); // Init physics if (bEnablePerPolyCollision == false) {  InitArticulated(GetWorld()->GetPhysicsScene());  USceneComponent::OnCreatePhysicsState(); // Need to route CreatePhysicsState, skip PrimitiveComponent } else {  CreateBodySetup();  BodySetup->CreatePhysicsMeshes();  Super::OnCreatePhysicsState(); //If we're doing per poly we'll use the body instance of the primitive component } // Notify physics created OnSkelMeshPhysicsCreated.Broadcast();}

而当我们勾选SkeletalMesh资源文件里面的EnableperpolyCollision时,他会先把之前Cook的数据清空,然后再去判断是否需要Cook,这时候没有Cook数据肯定是需要Cook的。

#if WITH_EDITORvoid USkeletalMesh::BuildPhysicsData(){ CreateBodySetup(); BodySetup->CookedFormatData.FlushData(); //we need to force a re-cook because we're essentially re-creating the bodysetup so that it swaps whether or not it has a trimesh BodySetup->InvalidatePhysicsData(); BodySetup->CreatePhysicsMeshes();}#endif

进一步再深入一点就是既然SkeletalMesh里面有Cook过的数据,直接用他Cook数据不就可以了?因为编辑器加载SkeletalMeshComponent的时候就会尝试去获取Cook后的信息,如果没有Cook后的信息就会尝试去进行Cook。不过这时候需要执行ContainsPhysicsTriMeshData判断当前对象是否有三角面信息。如果有的话才会进一步的进行Cook。如果没有的话,那就是空的Cook后的信息。所以无论是不是空的,这个数据都会返回给SkeletalMesh的BodySetup的CookedFormatData。这样,CookedFormatData虽然有这样一个平台以及对应的Cooked数据成员,但是里面的Cooked数据可能是空的。