I recently bumped into this problem and found a solution. It needs a bit of C++ know how; it’s a just copy, paste, and build solution (watch a tutorial). It does the job pretty well in my project, so it should work for you too. Wahooney makes no guarantees as to the marketability, usefulness, or stability of this solution, use at your own risk, etc.
UFUNCTION(BlueprintCallable)
static bool SetPrimitiveOverrideMass(
UPrimitiveComponent* InComponent,
const float InMass = 1.0f,
const bool OverrideMass = true)
{
if (InComponent)
{
// unlike the built-in function, get the unwelded body instance
if (auto* BodyInstance = InComponent->GetBodyInstance(NAME_None, false))
{
BodyInstance->SetMassOverride(InMass, OverrideMass);
// update the mass properties on the welded body instance
// sometimes this is the only one that exists
if (auto* MainBodyInstance = InComponent->GetBodyInstance(NAME_None, true))
{
MainBodyInstance->UpdateMassProperties();
return true;
}
}
}
return false;
}
Hope this helps.
Details for Filthy Nerds
The problem is that the built-in function gets the welded physics body by default and seems to only affect the mass of the primary body. This new function gets the unwelded body, overrides its mass, and updates the welded body mass properties (combined mass, center of mass, etc.) This will be slightly less performant, but if you’re doing this more than once per tick on average you may have other problems. Even once per tick is a bit crazy… What are you even making?
EDIT
The following function gets the mass of a single unwelded body if anyone needs it:
UFUNCTION(BlueprintPure)
static float GetPrimitiveMass(UPrimitiveComponent* InComponent)
{
if (InComponent)
{
// unlike the official function, get the unwelded body instance
if (const auto* BodyInstance = InComponent->GetBodyInstance(NAME_None, false))
{
return BodyInstance->bOverrideMass ? BodyInstance->GetMassOverride() : BodyInstance->GetBodyMass();
}
}
return 0.0f;
}