Search Unity

Feature Request Get applied Torque from AddForceAtPosition method

Discussion in 'Physics' started by Epsilon_Delta, Jan 2, 2024.

  1. Epsilon_Delta

    Epsilon_Delta

    Joined:
    Mar 14, 2018
    Posts:
    258
    Currently, there is no way to retrieve torque that is applied when using AddForceAtPosition.
    I suggest that either get torque as a return value from this function, or if it goes against some programming paradigm (like having side effects and return value), then add method e.g. CalculateTorqueFromForceAtPosition.

    Sure it is fairly easy to implement this and I have made an extension method that does exactly that, but since the AddForceAtPosition method implementation is hidden in .dll, I think it would be better if it was provided by Unity. Applies to 3D and 2D physics.
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    The methods Rigidbody.GetAccumulatedForce and Rigidbody.GetAccumulatedTorque give you the amounts of force and torque that have been applied to the Rigidbody so far in the current simulation step.

    So if you only call AddForceAtPosition once, then GetAccumulatedTorque will return the torque that has been applied to the Rigidbody as result of it.

    Unity uses PhysX 4 for 3D physics, and the source code is available on GitHub:


    The implementation of AddForceAtPosition is here:


    Essentially, it calculates the torque (which you've already calculated) and then applies both the force and the torque at the center of mass of the rigidbody.

    In 2D physics, Unity uses Box2D with source code also available on GitHub. Here's the implementation of AddForceAtPosition 2D:

     
    Epsilon_Delta and MelvMay like this.
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,463
    Edy and Epsilon_Delta like this.
  4. Epsilon_Delta

    Epsilon_Delta

    Joined:
    Mar 14, 2018
    Posts:
    258
    Good point, but my case is more complicated.
    As I said, it's easy to replicate/reverse engineer/find on github, that is not an issue. Just something that in my humble opinion should/could be part of Unity physics API by default.
    The argument about it being hidden in .dll - Unity can do something on top of the PhysX method and also it's about convenience - I can't immediately see what is going on.

    Good to know, thanks, h̶o̶p̶e̶ ̶i̶t̶ ̶w̶i̶l̶l̶ ̶g̶e̶t̶ ̶a̶d̶o̶p̶t̶e̶d̶ ̶b̶y̶ ̶3̶D̶ ̶p̶h̶y̶s̶i̶c̶s̶ ̶a̶s̶ ̶t̶h̶a̶t̶ ̶i̶s̶ ̶m̶y̶ ̶m̶a̶i̶n̶ ̶c̶o̶n̶c̶e̶r̶n̶ (edit: GetAccumulatedForce/Torque is the equivalent in 3D)
     
    Last edited: Jan 4, 2024
  5. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    I see, I understand your point. Regarding rigid body dynamics, as far as I know, Unity simply exposes the PhysX API as it is. The only situations I'm aware of where there's significant functionality hidden behind the scenes are related to the PhysX Vehicle SDK (WheelCollider). However, that's a very special case.
     
    Epsilon_Delta likes this.
  6. Epsilon_Delta

    Epsilon_Delta

    Joined:
    Mar 14, 2018
    Posts:
    258
    I just now realized what were you actually saying and that I should combine these two pieces of information:
    so I could make my method like this:

    Code (CSharp):
    1.     public static Vector3 AddForceAtPositionGetTorque(this Rigidbody rigidBody, Vector3 force, Vector3 position,
    2.         ForceMode mode = ForceMode.Force)
    3.     {
    4.         var torque = Vector3.Cross(position - rigidBody.worldCenterOfMass, force);
    5.         //rigidBody.AddForce(force, mode);
    6.         //rigidBody.AddTorque(torque, mode);
    7.         var before = rigidBody.GetAccumulatedTorque().z; // Only interested in "z" others are 0
    8.         rigidBody.AddForceAtPosition(force, position, mode); // Same as above, but try Unity's method
    9.         var after = rigidBody.GetAccumulatedTorque().z;
    10.         Debug.Log($"{before} | {after} | {after - before}");
    11.         Debug.Log(torque.z);
    12.         return torque;
    13.     }
    But the "torque" calculated from cross product is not the same as "after - before". However the physics simulation is correct wether I use my calculated torque or use unity's AddForceAtPosition and then return my calculated torque (and use it further). What am I doing wrong?
     
    Last edited: Jan 4, 2024
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,463
    No, I thought I was explicit when I mentioned 2D physics. I'm not a 3D physics engineer. I've not dug into the 3D physics side here.
     
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    The code looks good to me. However, I'd check and debug the vector values in any case, not just the Z.

    If the physics simulation is correct in both cases then the discrepancy must not be relevant. Numeric imprecisions might be kicking in that may make the numbers to look different. These might come from different ways of calculating the torque, such as using world center of mass vs. local center of mass, or if/how/where the values are transformed into local space.
     
    Epsilon_Delta and MelvMay like this.
  9. Epsilon_Delta

    Epsilon_Delta

    Joined:
    Mar 14, 2018
    Posts:
    258
    Certainly, it's just that GetAccumulationForce sounded like a direct 3D counterpart.

    It's a top down game with only Z rotation allowed.
    The discrepancy is of relevant order of magnitude however. E.g. torque from my cross product is 11 and torque from difference is 6. But I suspect it is something like the center of mass or different coordinate system in use. I will try to play with it some more.
     
  10. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Even in that case, I'd monitor the 3D parameters. For example, the value of the inertia tensor may induce a rotation around a different axis even if you apply your force expecting a perfect rotation around Z.

    EDIT: Even if your rigidbody constraints allow Z rotation only, since PhysX 3 (Unity 5) I've seen cases of these constraints being violated in apparently regular situations.
     
  11. Epsilon_Delta

    Epsilon_Delta

    Joined:
    Mar 14, 2018
    Posts:
    258
    Me too. And I monitor them (and they are zero as they should be), it's just a simplified code for the sake of this thread. I set center of mass to pivot point (Vector3.zero) and inertia tensor to (0, 0, some positive value) from a script.

    Btw. those unwanted rotations even if constraints are in place were in my experience caused by default center of mass being sometimes not aligned with pivot point for whatever reason and I had to set it to Vector3.zero. I guess the auto center of mass is calculated from colliders/mesh geometry.
     
    Last edited: Jan 7, 2024
    Edy likes this.