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:

  1. AddForceAtPosition for each thruster.
  2. Figure out the total force and torque being applied by the thrusters, plus the force of gravity.
  3. 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?

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.

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.