UE4随笔 Landscape动态Attach之后没有碰撞怎么解决?

it2023-05-11  83

本帖纯属个人原创,如有转载请注明出处

 

很多时候需求是这样的,想达到场景中所有的Actor统一旋转的功能。纯代码无观赏性,大家有实际需求的自然能看懂。

接到这样的需求,大家就会想将所有的actor全部都attach到一个父节点上,编辑器中Landscape无法进行Attach, 并且InstancedFoliageActor场景中也没有。那么就需要我们在代码中动态的进行Attach。

下面的支点Actor就是父节点, RootActor。

//将LandscapeActor Attach到支点Actor void LandscapeAttachToPivotActor(); //将InstancedFoliage Attach到支点Actor void InstancedFoliageAttachToPivotActor(); //将LandscapeActor Attach到支点Actor void USPDynamicDataComponent::LandscapeAttachToPivotActor() {     //Landscape类型的Actor比较特殊, 需要将这种类型的Actor代码挂接到支点Actor上     //(为什么说比较特殊, 和其他的相比, 这种Actor不能看到子控件, 不能调整移动性, 故不能像其他Actor在编辑器中调整)     //地形     TArray<AActor*> LandScapesActors;     UGameplayStatics::GetAllActorsOfClass(this, ALandscape::StaticClass(), LandScapesActors);     for (auto LandScapeActor : LandScapesActors)     {         //不处理level streaming的资源         bool bLevelStreamingAssest = false;         for (FName tag : LandScapeActor->Tags)         {             bLevelStreamingAssest = tag.ToString().Contains("LevelStreamingAssest");             BREAK_IF_TRUE(bLevelStreamingAssest);         }         if (bLevelStreamingAssest)             continue;         if (LandScapeActor->GetAttachParentActor() != SPPivotMeshActor)         {             //线设置成Movable才可以attach             int32 LandScapeComponentsNum = LandScapeActor->GetComponents().Array().Num();             for (int j = 0; j < LandScapeComponentsNum; j++)             {                 UActorComponent* pAC = LandScapeActor->GetComponents().Array()[j];                 USceneComponent* pSC = Cast<USceneComponent>(pAC);                 if (!pSC) continue;                 pSC->SetMobility(EComponentMobility::Movable);             }             LandScapeActor->AttachToActor(SPPivotMeshActor, FAttachmentTransformRules::KeepWorldTransform);         }     } } //将InstancedFoliage Attach到支点Actor void USPDynamicDataComponent::InstancedFoliageAttachToPivotActor() {     //地表     TArray<AActor*> InstancedFoliageActors;     UGameplayStatics::GetAllActorsOfClass(this, AInstancedFoliageActor::StaticClass(), InstancedFoliageActors);     AActor* pActor = nullptr;     TArray<AActor*> LandScapesActors;     UGameplayStatics::GetAllActorsOfClass(this, ALandscape::StaticClass(), LandScapesActors);          if (LandScapesActors.Num() > 0)     {         pActor = LandScapesActors[0];     }     else     {         pActor = SPPivotMeshActor;     }     for (auto InstancedFoliageActor : InstancedFoliageActors)     {         if (InstancedFoliageActor->GetAttachParentActor() != pActor)         {             int32 LandScapeComponentsNum = InstancedFoliageActor->GetComponents().Array().Num();             for (int j = 0; j < LandScapeComponentsNum; j++)             {                 UActorComponent* pAC = InstancedFoliageActor->GetComponents().Array()[j];                 USceneComponent* pSC = Cast<USceneComponent>(pAC);                 if (!pSC) continue;                 pSC->SetMobility(EComponentMobility::Movable);             }             InstancedFoliageActor->AttachToActor(pActor, FAttachmentTransformRules::KeepWorldTransform);         }     } }

通过上面的方法我们就能将地表和刷的植被附加到RootActor/ParentActor上了。

 

此时行走在LandScape上会发现地表并没有碰撞,通过如下方式解决即可。

//将LandscapeActor Detach从Actor, 为什么要Detach?这个地形不能从属其他actor, 否则没有碰撞 void LandscapeDetachToPivotActor(); //将LandscapeActor Detach从Actor, 为什么要Detach?这个地形不能从属其他actor, 否则没有碰撞 void USPDynamicDataComponent::LandscapeDetachToPivotActor() {     TArray<AActor*> LandScapesActors;     UGameplayStatics::GetAllActorsOfClass(this, ALandscape::StaticClass(), LandScapesActors);     for (auto LandScapeActor : LandScapesActors)     {         if (LandScapeActor->GetAttachParentActor() == SPPivotMeshActor)         {             //相反attach不同的是, 需要先detach再设置静态             FDetachmentTransformRules detachmentRules(EDetachmentRule::KeepWorld, false);             LandScapeActor->DetachFromActor(detachmentRules);             LandScapeActor->SetActorEnableCollision(true);             int32 LandScapeComponentsNum = LandScapeActor->GetComponents().Array().Num();             for (int j = 0; j < LandScapeComponentsNum; j++)             {                 UActorComponent* pAC = LandScapeActor->GetComponents().Array()[j];                 USceneComponent* pSC = Cast<USceneComponent>(pAC);                 if (!pSC) continue;                 pSC->SetMobility(EComponentMobility::Static);             }         }     } }

通过调用上面的方法,即可解决没有碰撞的问题,当我们需要实现旋转逻辑时, 调用Attach。当我们需要行走在地表上时,再调用Detatch逻辑。

 

下一篇写,如何巧妙的解决旋转整体模型带来的帧率下降。

希望能帮助到大家。谢谢。

最新回复(0)