Suspension physics via movement component

Hello,

I have been at this for days now and have had no luck :frowning: I am trying to implement fun arcade style driving mechanic via my trucks movement component (inherits from PawnMovementComponent).

Now physics is probably my weakest area in game dev, but I’ve been searching high and low for solutions to this.
I have come across videos, most noteable this: YouTube Video to which he expanded more on his video on Reddit here But no matter what I do the most I’ve had I’ve achieved is have the car bob up and down continuously without it ever coming to a stop OR failing that the car just slowly falls to the floor.

Searching some more I’ve found the equation for the spring physics with damping (F = -kX + k2 dX/dt) which was explained a bit here but I am in the same place as I was before.

Could anyone care to point me in the right direction please? Below is the function which is called to calculate force per wheel which is called every Tick on my MovementComponent.

void UTruckMovementComponent::CalculateSuspensionOnWheels(float DeltaTime)
{
if (!ensure(UpdatedPrimitive))
    return;

for (auto& Wheel : Wheels)
{
	if (!ensure(Wheel.WheelComponent))
		continue;

	// Project the current velocity onto the vehicles up vector
	FVector Cf = Wheel.CurrentSuspensionVelocity.ProjectOnTo(UpdatedPrimitive->GetUpVector());

	// Start and end points of trace
	FVector WorldPosition = Wheel.WheelComponent->GetComponentLocation();
	FVector TraceEndPosition = WorldPosition - (UpdatedPrimitive->GetUpVector() * MaxSuspensionReach);

	// Do line trace
	FHitResult HitResult;
	bool bHitAnything = GetWorld()->LineTraceSingleByChannel(HitResult, WorldPosition, TraceEndPosition, ECollisionChannel::ECC_Camera);

	// Set compression ratio, if there is no hit this shouuld be 0
	float CompressionRatio = 0.0f;
	if (bHitAnything)
	{
		float DistPercent = ((HitResult.ImpactPoint - WorldPosition).Size() / MaxSuspensionReach);
		CompressionRatio = 1.0f - FMath::Clamp(DistPercent, 0.0f, 1.0f);
	}
    
    // Calculate the new force this frame.
	FVector Nf = UpdatedPrimitive->GetUpVector() * CompressionRatio * SuspensionForce;
    
    // Calculate delta between the old and new (last frame and this frame)
	FVector Df = (Nf - Cf) / DeltaTime;
    
    DrawDebugString(GetWorld(), WorldPosition + FVector::UpVector * 50, FString::Printf(TEXT("%.2f"), CompressionRatio), nullptr, FColor::White, DeltaTime * 0.75f);
    
    // Add the new force to the truck at the position of the wheel.
	UpdatedPrimitive->AddForceAtLocation((-Nf + Df) * UpdatedPrimitive->GetMass(), WorldPosition);
    
    // Cache values which will be needed later on
	Wheel.LastCompressionRatio = CompressionRatio;
	Wheel.LastSurfaceImpactPoint = HitResult.ImpactPoint;
	Wheel.LastSurfaceImpactNormal = HitResult.ImpactNormal;
    Wheel.CurrentSuspensionVelocity = Nf;
}
}

Hi there, Do you found any fix on this? I am also not so great in physics, especially Vehicle physics.