#### Search Unity

Discussion in 'Physics' started by jtomes123, Dec 23, 2014.

1. ### jtomes123

Joined:
Dec 18, 2012
Posts:
7
Hi, I decided to make "realistic" space game. I have working thrusters and now I am trying to create something similar to flight assistant which would help you to turn your ship, but I don't know how to calculate torque that will be added when I perform addForceAtPosition.

2. ### MatthewW

Joined:
Nov 30, 2006
Posts:
1,355
I'm pretty sure the Unity function just maps directly to PhysX's addForceAtPos() function, which doesn't expose or return any of the math.

I guess you could look into building your own AddForceAtPosition function, so you know exactly what's going on under the hood, or try to build the flight assistant around watching other parameters like rigidbody.angularVelocity after the fact...

http://docs.unity3d.com/ScriptReference/Rigidbody-angularVelocity.html

3. ### Partel-Lang

Joined:
Jan 2, 2013
Posts:
2,173
Hi!

Code (CSharp):
1. /// <summary>
2.     /// Calculates the change of angular velocity for the attached Rigidbody if a force were to applied to it at a position.
3.     /// </summary>
4.     /// <returns>Angular velocity delta.</returns>
5.     /// <param name="force ">Force (world space).</param>
6.     /// <param name="position)">Position (world space).</param>
7.     /// <param name="forceMode">Force mode.</param>
8.     public Vector3 ForceToTorque(Vector3 force, Vector3 position, ForceMode forceMode = ForceMode.Force) {
9.         Vector3 t = Vector3.Cross(position - rigidbody.worldCenterOfMass, force);
10.         ToDeltaTorque(ref t, forceMode);
11.
12.         return t;
13.     }
14.
15.     private void ToDeltaTorque(ref Vector3 torque, ForceMode forceMode) {
16.         bool continuous = forceMode == ForceMode.Force || forceMode == ForceMode.Acceleration;
17.         bool useMass = forceMode == ForceMode.Force || forceMode == ForceMode.Impulse;
18.
19.         if (continuous) torque *= Time.fixedDeltaTime;
20.         if (useMass) ApplyInertiaTensor(ref torque);
21.     }
22.
23.     private void ApplyInertiaTensor(ref Vector3 v) {
24.         v = rigidbody.rotation * Div(Quaternion.Inverse(rigidbody.rotation) * v, rigidbody.inertiaTensor);
25.     }
26.
27.     private static Vector3 Div(Vector3 v, Vector3 v2) {
28.         return new Vector3(v.x / v2.x, v.y / v2.y, v.z / v2.z);
29.     }
The first function will give you the delta angular velocity that would be added to the Rigidbody if you called AddForceAtPosition with the exact same parameters.

Linear velocity (rigidbody.velocity) delta just equals to force, but you'll have add fixedDeltaTime and divide by mass similar to whats happening in ToDeltaTorque to account for the different force modes.

Cheers,
Pärtel

4. ### BenZed

Joined:
May 29, 2014
Posts:
524
Hey @Partel Lang! I just found this answer after searching for a similar answer for 2D physics.

This math is way beyond me! How would I adapt these functions to work in 2D?

5. ### Partel-Lang

Joined:
Jan 2, 2013
Posts:
2,173
Hey, no sweat

Code (CSharp):
1. public float ForceToTorque(Vector2 force, Vector2 position, ForceMode2D forceMode = ForceMode2D.Force) {
2.         // Vector from the force position to the CoM
3.         Vector2 p = rigidbody2D.worldCenterOfMass - position;
4.
5.         // Get the angle between the force and the vector from position to CoM
6.         float angle = Mathf.Atan2(p.y, p.x) - Mathf.Atan2(force.y, force.x);
7.
8.         // This is basically like Vector3.Cross, but in 2D, hence giving just a scalar value instead of a Vector3
9.         float t = p.magnitude * force.magnitude * Mathf.Sin(angle) * Mathf.Rad2Deg;
10.
11.         // Continuous force
12.         if (forceMode == ForceMode2D.Force) t *= Time.fixedDeltaTime;
13.
14.         // Apply inertia
15.         return t / rigidbody2D.inertia;
16.     }

Bvenjamin and Tset_Tsyung like this.
6. ### BenZed

Joined:
May 29, 2014
Posts:
524
Holy damn. Rocket science. You are a rocket scientist, arn't you? You build rockets.

Thank you so much!

One final question, could a variant of this method be used to determine the effect on the velocity, as well?

Something like so:

Code (CSharp):
1. public struct ForceResult {
2.     public Vector velocity;
3.     public float angularVelocity;
4.
5. }
6.
7. ForceResult ResultOfForceAtPosition(Vector2 force, Vector2 position, ForceMode2D forceMode = ForceMode2D.Force) {
8.      /*partels mathematical wizardry*/
9.     return new ForceResult();
10. }
I believe the result of AddForce is as simple as: velocity = force / mass * Time.fixedDeltaTime
But the linear velocity would be reduced the more torque that is added, so if the force is not added at the center, the above velocity equation wont be correct.

(...Right?)

Last edited: Jan 19, 2015
7. ### Partel-Lang

Joined:
Jan 2, 2013
Posts:
2,173
Building rockets is for nerds, lol

mr Newton's second law of motion states that the vector sum of the forces F on an object is equal to the mass m of that object multiplied by the acceleration vector a of the object:

F = ma

Using that we can find that the acceleration of an object is the sum of forces acting upon it divided by it's mass:

a = F/m

That works for simplified uniform constant mass objects such as Rigidbodies in Unity and acceleration a should be understood as the linear acceleration of the object's center of mass.

So linear acceleration would not be reduced by the amount of torque that results from the force as we would intuitively presume (angular velocity rotates an object about it's center of mass so it doesn't accelerate it).

Code (CSharp):
1. Vector2 v = force / rigidbody2D.mass;
2.         if (forceMode == ForceMode2D.Force) v *= Time.deltaTime;
Cheers,
Pärtel

chris_schubert and twobob like this.

Joined:
May 29, 2014
Posts:
524
9. ### ICONS

Joined:
Aug 8, 2017
Posts:
1
if you apply inverse torque... result should be zero (no turn)?

Code (CSharp):
1. var torque = ForceToTorque(transform.root.GetComponent<Rigidbody>(), thruster.transform.forward * z, thruster.transform.position);
2.