Download

Question about shock absorber physics for hover vehicle

I’m trying to create a hovered vehicle like this https://youtu.be/cPVaDndT7tY?t=15m44s

I’ve created the component shock absorber that works like in the video below. The problem is the vehicle is bouncing like in the video.

The guy on the video fix this problem by adding some linear damping that is not what I want because the gravity force not works correctly with linear Damping.

So the question is how much force must develop each shock absorber for each frame to create something stable like this: https://youtu.be/LG1CtlFRmpU?t=4m38s

I thought that when the raycast is touching the ground and is full extended the force that must be applied to vehicle is just the opposite of gravity force, and must increase when the raycast length is less that 100%.

This not works… So what I miss?
Thanks in advance

1cdcd4cc8cfcf0e503a12b58f3db675ac9b7fc7d.png

Damping is essential for stable hovering/spring physics. It’s impossible to get stability without it.

Here’s some basic code for a stable, hovering object.



	// Trace below for hovering
	FHitResult HoverHit = FHitResult();
	const FVector Location = UpdatedComponent->GetComponentLocation();
	FVector HoverAccel = FVector::ZeroVector;

	FCollisionQueryParams Params = FCollisionQueryParams();
	Params.AddIgnoredActor(GetOwner());
	Params.bTraceComplex = true;

	if (GetWorld()->LineTraceSingleByChannel(HoverHit, Location, Location + FVector(0.f, 0.f, -HoverSpring_Length), ECC_Visibility, Params))
	{
		const float CompressionRatio = FMath::GetMappedRangeValueClamped(FVector2D(0.f, HoverSpring_Length), FVector2D(1.f, 0.f), Location.Z - HoverHit.Location.Z);
		const float HoverAccelZ = (CompressionRatio * HoverSpring_Tension) + (-HoverSpring_Damping * Velocity.Z);

		HoverAccel = FVector(0.f, 0.f, HoverAccelZ);
	}

        Accel = HoverAccel; // Add your other accelerations here
        Velocity += Accel * DeltaTime;


You can apply that to a physics-simulating object with gravity and shouldn’t have any trouble, alternatively you can just add FVector(0.f, 0.f -980.f) to Accel before adding it to Velocity, if you want custom gravity. You will also need to tweak the values. I recommend starting with something like this:



SpringTension = 1500.f;
SpringDamping = 1.5f;
SpringLength = 350.f;


I do my hovertanks with one downward-facing trace, and another trace that follows the velocity of the craft, and average the results. I use a rotational spring to align to the surface normal rather than using multiple traces. It’s more stable, faster, and you can control the strength of surface alignment.

So you work with linear velocity instead of adding force at location. Why do you do in this way?

Or how can I add Velocity to a single position of body? because I’m trying to create something like this: https://youtu.be/LG1CtlFRmpU?t=4m38s

Well in my case it’s because angular velocity shouldn’t be affected by the spring, and I only do a single trace.

For force, just use the ‘accel’ value and plug it straight into ‘Add Force At Position’. When doing the damping equation, you need to use ‘Get Velocity at Location’ as well and not use general velocity, and pass in the bone you’re doing the trace from.

Ok understood. But if I need maintain the Box Component at 100cm height how much force and dumping I need to submit?

I’ve not understand the conversion from Newton to unreal Force.

This this how i’m calculating the force for each Shock absorber:



float MaxForce = 2000000.0;
float Damping = 6000;

FHitResult HitResult;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredComponent(ParentComponent);

FVector ComponentWorldLocation(GetComponentToWorld().GetLocation());
FVector TargetLocation = ComponentWorldLocation - GetUpVector() * ShockMaxWith;

if (GetWorld()->LineTraceSingleByChannel(HitResult, ComponentWorldLocation, TargetLocation, ECollisionChannel::ECC_WorldDynamic, QueryParams)) {
				
	float Inverse_FloorDistancePercent = 1 - ((HitResult.ImpactPoint - ComponentWorldLocation).Size() / ShockMaxWith);

	FVector ShockForce = HitResult.ImpactNormal * MaxForce * Inverse_FloorDistancePercent;

	// Add dumping
	ShockForce -= Damping * ParentComponent->GetPhysicsLinearVelocityAtPoint(ComponentWorldLocation);
        ParentComponent->AddForceAtLocation(ShockForce, ComponentWorldLocation, NAME_None);

}


As you can see the Force and dumping i’m submitting are too higher than yours. So how can I calculate the right force to submit?
Currently the box is stable in the air but i’ve inserted these parameters randomly

To get to 100cm specifically I’m not sure, you’d have to look up spring physics and see how the resting spring length is affected by mass / tension etc. The short answer is just keep tweaking it until it’s right.

Make sure you’re apply the Force as Acceleration (should be a bool you can pass into AddForceAtLocation), otherwise the forces required will change depending on the objects PhysX mass. Also means you don’t have to use such high values.

Ok, I’ve understood. Thanks alot for the help!! Thanks too much