I found a solution to this after a little bit of work and some help from Rama’s tutorial on integrating PhysX code in to your project. First off I needed to include the PhysX and APEX modules in my Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "PhysX", "APEX" });
I added the following includes to my class.
#include "PhysXIncludes.h"
#include "PhysicsPublic.h"
#include "PhysXPublic.h"
Then I created the following function.
TArray<FHitResult> UFunctionLibrary::MultiHitTrace(UWorld* World, FVector Start, FVector End)
{
FVector Delta = End - Start;
float DeltaMag = Delta.Size();
FPhysScene* PhysScene = World->GetPhysicsScene();
PxScene* scene = PhysScene->GetPhysXScene(PST_Sync);
PxVec3 origin = U2PVector(Start);
PxVec3 unitDir = U2PVector(Delta / DeltaMag);
PxReal maxDistance = DeltaMag;
const PxU32 bufferSize = 256;
PxRaycastHit hitBuffer[bufferSize];
PxRaycastBuffer buf(hitBuffer, bufferSize);
PxHitFlags POutputFlags = PxHitFlag::eMESH_MULTIPLE | PxHitFlag::eMESH_BOTH_SIDES;
scene->raycast(origin, unitDir, maxDistance, buf, POutputFlags);
FHitResult HitResult;
TArray<FHitResult> Hits;
for (PxU32 i = 0; i < buf.nbTouches; i++)
{
HitResult.Location = (P2UVector(buf.touches[i].position));
PxShape* PShape = buf.touches[i].shape;
PxU32 FaceIndex = buf.touches[i].faceIndex;
UPhysicalMaterial* PhysMaterial;
if (PxMaterial* PxMat = PShape->getMaterialFromInternalFaceIndex(FaceIndex))
{
PhysMaterial = FPhysxUserData::Get<UPhysicalMaterial>(PxMat->userData);
HitResult.PhysMaterial = PhysMaterial;
}
}
return Hits;
}
I only wanted the location of the hit and the physical material so that is all the FHitResult returns.
Hopefully this will be useful to someone in the future. Warning to anyone who wants to use this function, it is a very particular use case that is more expensive than the solutions offered by the engine, for most purposes the LineTrace or MultiLineTrace should suffice.