Change Friction or Coefficient of Restitution at Runtime

I would like to change the friction and/or coefficient of restitution of mesh at run time in blueprints. I know this can be done with pre-assigned materials, but I want the ability to set the values programmatically.

Unfortunately, I found the short answer is that this can’t be done in blueprint, but it can be done in C++. If you make a function library for your project here’s a solution to make a custom blueprint block to solve this issue! I did this in 4.26, but I expect it will work in later versions of UE4 as well.

In the .h:

#include "PhysicalMaterials/PhysicalMaterial.h"

UFUNCTION(BlueprintCallable, Category = "MyCustomPhysicsLibrary", Meta = (DefaultToSelf = Object, DisplayName = "Set Physical Material Details", Keywords = " MyCustomPhysicsLibrary physical physics material friction restitution"))
		static void SetPhysicalMaterialDetails(UStaticMeshComponent* Mesh, float StaticFriction, float DynamicFriction, bool bOverrideFrictionCombineMode, TEnumAsByte<EFrictionCombineMode::Type> FrictionCombineMode, float Restitution, bool bOverrideRestitutionCombineMode, TEnumAsByte<EFrictionCombineMode::Type> RestitutionCombineMode);

In the .cpp:

void UMyCustomPhysicsLibrary::SetPhysicalMaterialDetails(UStaticMeshComponent* Mesh, float StaticFriction, float DynamicFriction, bool bOverrideFrictionCombineMode, TEnumAsByte<EFrictionCombineMode::Type> FrictionCombineMode, float Restitution, bool bOverrideRestitutionCombineMode, TEnumAsByte<EFrictionCombineMode::Type> RestitutionCombineMode) {

		
	UPhysicalMaterial* PhysicalMaterial = NewObject<UPhysicalMaterial>();
	
	PhysicalMaterial->Friction = DynamicFriction;
	PhysicalMaterial->StaticFriction = StaticFriction;
	PhysicalMaterial->FrictionCombineMode = FrictionCombineMode;
	PhysicalMaterial->bOverrideFrictionCombineMode = bOverrideFrictionCombineMode;
	PhysicalMaterial->Restitution = Restitution;
	PhysicalMaterial->RestitutionCombineMode = RestitutionCombineMode;
	PhysicalMaterial->bOverrideRestitutionCombineMode = bOverrideRestitutionCombineMode;

	PhysicalMaterial->AddToRoot(); // this is done to prevent it from being garbage collected
	Mesh->SetPhysMaterialOverride(PhysicalMaterial);
}

In the .cs, make sure you include “PhysicsCore”. It isn’t listed as a required module in the C++ docs, but you’ll get a compile error without it. The end result is a block that looks like this:

Connect the mesh you want to change and enter your new parameters. It is effectively creating a new physics material and using the Phys Material Override to change it on a per-mesh basis.

One additional tip, the first time you create a new blueprint block, I find you need to restart UE4 to make it visible in the search list. After that, you can update the C++, build, and then just do a refresh on the block if you modified the parameter list.

2 Likes

Thanks @Dr.Widgit for sharing a way to do it. It seems to be working for me as well.

Is there another way via "PostEditChangeProperty? Since the above function would create physical material at each tick? RIght.

Possibly, as long as this is the only object using the material. I first tried experimenting with just modifying an existing material, but it isn’t like a dynamic material instance. If you modify a physics material it will affect all existing objects using that material as well. In my particular instance, I needed unique materials per mesh, but definitely don’t do this on tick or you’re right, it will create a new material each time.

The other limitation of this approach is the physics materials probably won’t be garbage collected even if you assign a new material since it was added to the root. If you know the material is only used on a single mesh, then you can probably comment out that line, but I’m not overly familiar with the inner workings of the C++ to say for sure.

I posted same Questin here in UDN. Just waiting for their reply.

I think there is a way to update physics material in runtime with UpdateMaterial() method. Thing is I am just waiting for devs for proper response.