I’ve spent quite a long while finding a solution for that. What I found is that dynamic and static friciton can be modified via FContactModifyCallback
in C++ code. You set up a callback function that will be called by PhysX when two objects collide. You can then, within that callback modify the friction properties. This way I can even control friction on per object basis.
Create a class with a proper callback:
class FPhysicalContactsModifier : public FContactModifyCallback
{
public:
FPhysicalContactsModifier();
~FPhysicalContactsModifier();
void onContactModify(
physx::PxContactModifyPair* const pairs,
physx::PxU32 count) override;
};
Code to setup the callback:
auto* PhysicsScene = GetWorld()->GetPhysicsScene()
if (auto* PhysXScene = PhysicsScene->GetPxScene())
{
SCOPED_SCENE_WRITE_LOCK(PhysXScene);
// Note: to enable contact-modification on given body,
// call: BodyInstance->SetContactModification(true);
PhysXScene->setContactModifyCallback(&PhysicalContactsModifier);
}
You also have to enable contact-modification for each BodyInstance you are interested in:
BodyInstance->SetContactModification(true);
And then in FPhysicalContactsModifier::onContactModify you can change friction properties of a specific contact between two physical actors.
Pair.contacts.setStaticFriction(contactIdx, 0.0f);
Pair.contacts.setDynamicFriction(contactIdx, 0.0f);
You then probably want to know which UE4 actors are colliding. You can learn that by translating PxActor* to AActor*:
AActor* PhysicsUtils::PxActorToActor(const physx::PxRigidActor& PxActor)
{
if (FPhysxUserData::IsGarbage(PxActor.userData))
return nullptr;
auto* BodyInstance = FPhysxUserData::Get<FBodyInstance>(PxActor.userData);
if (BodyInstance && BodyInstance->OwnerComponent.IsValid())
{
auto* OwnerActor = BodyInstance->OwnerComponent->GetOwner();
return OwnerActor;
}
return nullptr;
}