- Home /
Get result (force & torque) of AddForceAtPosition?
Here's my scenario:
I've got a hovercraft with four "thrusters" that lift it off the ground. Each thruster uses AddForceAtPosition to push the hovercraft, and the player controls the craft by increasing or decreasing the amount of force that each thruster applies.
I want to be able to automatically make the hovercraft hover to a stop in mid-air. What I want to do is this:
AddForceAtPosition for each thruster.
Figure out the total force and torque being applied by the thrusters, plus the force of gravity.
Slowly apply an opposite force to bring the hovercraft to a halt.
Step 2 is the part that I can't figure out how to do with Unity.
My current work-around gets the velocity, and then applies an opposite force. This almost brings it to a stop, but not quite. When I calculate force from velocity, but the velocity doesn't update immediately when you apply force. This code demonstrates issue is:
FixedUpdate() {
Debug.log(rigidB.velocity);
//output: (0, 0, 0)
rigidB.AddForceAtPosition(new Vector3(100, 0, 0), new Vector3(10, 0, 0));
Debug.log(rigidB.velocity);
//output: (0, 0, 0)
}
I wish I could do something like this:
FixedUpdate() {
rigidB.AddForce(new Vector3(100, 0, 0));
rigidB.AddForce(new Vector3(100, 0, 0));
Debug.log(rigidB.forces);
//output: (200, 0, 0)
}
But I don't think there's any way to access the current force being applied to a rigidbody.
If I was just using AddForce, I could do this
FixedUpdate() {
Debug.log(rigidB.velocity);
//output: (0, 0, 0)
Vector3 totalForce = Vector3.zero;
totalForce += new Vector3(100, 0, 0));
totalForce += new Vector3(100, 0, 0));
Debug.log(totalForce );
//output: (200, 0, 0)
}
But that won't work when I use AddForceAtPosition. So what I'm asking for is a "ForceAtPosition to Force" that can be broken-down into force and torque. Something like this:
ForceAtPosition f = new ForceAtPosition(new Vector3(0, 10, 0), new Vector3(5, 0, 0), rigidB);
Debug.log(f.force);
//output: (3.2, 3.2, 0)
Debug.log(f.torque);
//output: (5, 0, 0)
So, does anyone know how ForceAtPosition is calculated and turned into a force and a torque?
Answer by markefus · Jul 08, 2015 at 09:55 PM
Rather than trying to nullify the velocity with real physics (this is unfortunately extremely tedious due to race conditions for every frame, as you mentioned), manually set it to zero; gradually.
Here's a quick example:
//Really can be any number, you can tune the times
float LERP_TIME = 1.0f;
FixedUpdate()
{
if(whatever_condition_to_trigger_hover)
{
zeroVelocity();
}
}
void zeroVelocity()
{
//Current Velocity
Vector3 v = GetComponent<Rigidbody>().velocity;
//Gradually set the velocity
GetComponent<Rigidbody>().velocity = new Vector3(Mathf.Lerp(v.x, 0, LERP_TIME),
Mathf.Lerp(v.y, 0, LERP_TIME),
Mathf.Lerp(v.z, 0, LERP_TIME));
}
That's the general idea.
This doesn't work with gravity, though.
You can try this really easily: create a cube, and attach a script that sets velocity to 0 on FixedUpdate. The cube will slowly fall downwards, because gravity applies a force after FixedUpdate, but before movement/collision simulation.
I could disable gravity, but there's another problem: the thursters on the hovercraft are also keeping the hovercraft in level flight. If I disable gravity and lerp velocity to 0, the hovercraft will still be spinning freely.
To fix that issue, I could just also lerp the rotation towards 0. But this looks ugly and unconvincing. Normally, the hovercraft will level itself with a little bit of swaying, but lerp will just rotate and stop. Also, doing this will cancel out all angular velocity, which looks really weird.
Answer by PaulMakesThings · Jul 09, 2015 at 06:31 AM
I would suggest using a single application of force and torque to get the effect of the multiple thrusters that you are seeking. The combined force would be the sum of the force of all three thrusters applied to the whole object, the combined torque could be obtained by using the cross product of the offset vector (between the point of application and the center of gravity) and the force vector.
τ(torque)=r⃗ ×F⃗
Calculate these and then apply them with one application. Then you will know what the total is, your physics will be more stable and less CPU consuming, and if you want to apply an opposite force you can subtract it from the vector before you apply it, same goes for damping the torque.