UE4 只与指定的Actor发生碰撞

您所在的位置:网站首页 getuniqueid UE4 只与指定的Actor发生碰撞

UE4 只与指定的Actor发生碰撞

2024-07-13 07:54| 来源: 网络整理| 查看: 265

一个需求 分身功能 分身与角色自己不发生碰撞 但是与其他角色发生碰撞

因为不同的角色都是使用相同的碰撞通道 这就需要实现指定分身与自己不发生碰撞

参考 https://answers.unrealengine.com/questions/543433/view.html

直接上主要代码

WorldSetting.h

// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/WorldSettings.h" #include "MyWorldSettings.generated.h" USTRUCT() struct FIgnorePair { GENERATED_USTRUCT_BODY() public: TWeakObjectPtr obj1; TWeakObjectPtr obj2; bool operator ==(const FIgnorePair& V) { return obj1->GetUniqueID() == V.obj1->GetUniqueID() || obj2->GetUniqueID() == V.obj2->GetUniqueID(); } }; /** * */ UCLASS() class TESTCAR_API AMyWorldSettings : public AWorldSettings { GENERATED_BODY() public: AMyWorldSettings(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); public: private: TArray ignoreComponents; public: const TArray& GetIgnoreComponents(); void IgnoreBetween(USceneComponent* a, USceneComponent* b); bool RemoveIgnoreBetween(USceneComponent* a, USceneComponent* b); };

WorldSetting.cpp

// Fill out your copyright notice in the Description page of Project Settings. #include "MyWorldSettings.h" #include "Engine/World.h" #include "Physics/PhysicsFiltering.h" #include "MyPlayerController.h" //定义物理过滤函数 static PxFilterFlags PhysXSimFilterShaderPortal(PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize) { AMyWorldSettings* settings = nullptr; if (AMyPlayerController::currentWorld && AMyPlayerController::currentWorld->GetWorldSettings()) { settings = Cast(AMyPlayerController::currentWorld->GetWorldSettings()); } if (settings != nullptr) { const auto& ignoreComponents = settings->GetIgnoreComponents(); for (int i = 0; i < ignoreComponents.Num(); ++i) { const auto& pair = ignoreComponents[i]; if (pair.obj1.IsValid() && pair.obj2.IsValid()) { if ((pair.obj1->GetUniqueID() == filterData0.word2 && pair.obj2->GetUniqueID() == filterData1.word2) || (pair.obj2->GetUniqueID() == filterData0.word2 && pair.obj1->GetUniqueID() == filterData1.word2)) { return PxFilterFlag::eKILL; } } } } //原有的方法 bool k0 = PxFilterObjectIsKinematic(attributes0); bool k1 = PxFilterObjectIsKinematic(attributes1); PxU32 FilterFlags0 = (filterData0.word3 & 0xFFFFFF); PxU32 FilterFlags1 = (filterData1.word3 & 0xFFFFFF); if (k0 && k1) { //Ignore kinematic kinematic pairs unless they are explicitly requested if (!(FilterFlags0&EPDF_KinematicKinematicPairs) && !(FilterFlags1&EPDF_KinematicKinematicPairs)) { return PxFilterFlag::eSUPPRESS; //NOTE: Waiting on physx fix for refiltering on aggregates. For now use supress which automatically tests when changes to simulation happen } } bool s0 = PxGetFilterObjectType(attributes0) == PxFilterObjectType::eRIGID_STATIC; bool s1 = PxGetFilterObjectType(attributes1) == PxFilterObjectType::eRIGID_STATIC; //ignore static-kinematic (this assumes that statics can't be flagged as kinematics) // should return eSUPPRESS here instead eKILL so that kinematics vs statics will still be considered once kinematics become dynamic (dying ragdoll case) if ((k0 || k1) && (s0 || s1)) { return PxFilterFlag::eSUPPRESS; } // if these bodies are from the same component, use the disable table to see if we should disable collision. This case should only happen for things like skeletalmesh and destruction. The table is only created for skeletal mesh components at the moment #if !WITH_APEIRON && !PHYSICS_INTERFACE_LLIMMEDIATE if (filterData0.word2 == filterData1.word2) { check(constantBlockSize == sizeof(FPhysSceneShaderInfo)); const FPhysSceneShaderInfo* PhysSceneShaderInfo = (const FPhysSceneShaderInfo*)constantBlock; check(PhysSceneShaderInfo); FPhysScene * PhysScene = PhysSceneShaderInfo->PhysScene; check(PhysScene); const TMap & CollisionDisableTableLookup = PhysScene->GetCollisionDisableTableLookup(); TMap* const * DisableTablePtrPtr = CollisionDisableTableLookup.Find(filterData1.word2); if (DisableTablePtrPtr) //Since collision table is deferred during sub-stepping it's possible that we won't get the collision disable table until the next frame { TMap* DisableTablePtr = *DisableTablePtrPtr; FRigidBodyIndexPair BodyPair(filterData0.word0, filterData1.word0); // body indexes are stored in word 0 if (DisableTablePtr->Find(BodyPair)) { return PxFilterFlag::eKILL; } } } #endif // Find out which channels the objects are in ECollisionChannel Channel0 = GetCollisionChannel(filterData0.word3); ECollisionChannel Channel1 = GetCollisionChannel(filterData1.word3); // see if 0/1 would like to block the other PxU32 BlockFlagTo1 = (ECC_TO_BITFIELD(Channel1) & filterData0.word1); PxU32 BlockFlagTo0 = (ECC_TO_BITFIELD(Channel0) & filterData1.word1); bool bDoesWantToBlock = (BlockFlagTo1 && BlockFlagTo0); // if don't want to block, suppress if (!bDoesWantToBlock) { return PxFilterFlag::eSUPPRESS; } pairFlags = PxPairFlag::eCONTACT_DEFAULT; //todo enabling CCD objects against everything else for now if (!(k0 && k1) && ((FilterFlags0&EPDF_CCD) || (FilterFlags1&EPDF_CCD))) { pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT | PxPairFlag::eSOLVE_CONTACT; } if ((FilterFlags0&EPDF_ContactNotify) || (FilterFlags1&EPDF_ContactNotify)) { pairFlags |= (PxPairFlag::eNOTIFY_TOUCH_FOUND | PxPairFlag::eNOTIFY_TOUCH_PERSISTS | PxPairFlag::eNOTIFY_CONTACT_POINTS); } if ((FilterFlags0&EPDF_ModifyContacts) || (FilterFlags1&EPDF_ModifyContacts)) { pairFlags |= (PxPairFlag::eMODIFY_CONTACTS); } return PxFilterFlags(); } AMyWorldSettings::AMyWorldSettings(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { GSimulationFilterShader = PhysXSimFilterShaderPortal; } const TArray& AMyWorldSettings::GetIgnoreComponents() { // TODO: insert return statement here return ignoreComponents; } void AMyWorldSettings::IgnoreBetween(USceneComponent* a, USceneComponent* b) { FIgnorePair ComponentPair; ComponentPair.obj1 = a; ComponentPair.obj2 = b; ignoreComponents.Add(ComponentPair); } bool AMyWorldSettings::RemoveIgnoreBetween(USceneComponent* a, USceneComponent* b) { for (auto ComponentPair : ignoreComponents) { if (ComponentPair.obj1->GetUniqueID() == a->GetUniqueID() || ComponentPair.obj2->GetUniqueID() == b->GetUniqueID()) { ignoreComponents.Remove(ComponentPair); return true; } } return false; }

 

最后 测试工程链接

https://download.csdn.net/download/maxiaosheng521/11177614



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3