Hi,
Thanks for this info. We have an IgnoreActiveActors array which is meant to handle this case. When a BodyInstance is destroyed we add its physx actor to the IgnoreActiveActors array which we use to skip dangling pointers later on.
In the destructible case we have multiple physx actors which we are currently (incorrectly) not marking for ignoring. Can you try modifying UDestructibleComponent::OnDestroyPhysicsState so it looks like this:
void UDestructibleComponent::OnDestroyPhysicsState()
{
#if WITH_APEX
if(ApexDestructibleActor != NULL)
{
if(UWorld * World = GetWorld())
{
if (FPhysScene * PhysScene = World->GetPhysicsScene())
{
PxScene* PScene = nullptr;
TSet PActorsToRemove;
for (int32 ChunkIdx = 0; ChunkIdx < ChunkInfos.Num(); ++ChunkIdx)
{
if (PxRigidDynamic* PDynamic = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx))
{
PActorsToRemove.Add(PDynamic);
if (PScene == nullptr)
{
PScene = PDynamic->getScene();
}
}
}
const int32 SceneType = PScene == PhysScene->GetPhysXScene(PST_Sync) ? PST_Sync : PST_Async;
for (PxRigidDynamic* PDynamic : PActorsToRemove)
{
PhysScene->RemoveActiveRigidActor(SceneType, PDynamic);
}
GPhysCommandHandler->DeferredRelease(ApexDestructibleActor);
}
}
ApexDestructibleActor = NULL;
//Destructible component uses the BodyInstance in PrimitiveComponent in a very dangerous way. It assigns PxRigidDynamic to it as it needs it.
//Destructible PxRigidDynamic actors can be deleted from under us as PhysX sees fit.
//Ideally we wouldn't ever have a dangling pointer, but in practice this is hard to avoid.
//In theory anyone using BodyInstance on a PrimitiveComponent should be using functions like GetBodyInstance - in which case we properly fix up the dangling pointer
BodyInstance.RigidActorSync = NULL;
BodyInstance.RigidActorAsync = NULL;
}
#endif // #if WITH_APEX
Super::OnDestroyPhysicsState();
}
Please let me know if this doesn’t fix the issue, but hopefully this is the right fix in which case I will submit it into the engine for 4.19