[Question/Request] Change vehicle wheels friction at runtime

How change the wheels friction at runtime ?
I like change the friction of the wheels at blow out the tire. but i don’t see how.

And other settings of the vehicle (engine/wheels) are missing to change at runtime

Friction of car wheels depends more on tire-grips and ground surface. This friction is in turn helps your car to stop when applying break. If want to regulate the friction on runtime, I don’t think it is possible anyhow. However if you get able to maintain those two factors, then perhaps it could be possible for you.

Hello Hevedy,

From what I’ve looked into, it doesn’t seem like changing the friction value at runtime is possible natively in blueprints. The friction property itself is marked as a private variable in C++ and therefore isn’t accessible outside of the class. It most likely is to protect it from being changed at runtime as it may cause issues related to PhysX.

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;
}
1 Like