Search Unity

Resolved Wrong angle calculation with relative joints 2D

Discussion in 'Physics' started by dikar771, Aug 2, 2021.

  1. dikar771

    dikar771

    Joined:
    Oct 30, 2015
    Posts:
    19
    When angle -180+ meets -180- relative joint 2d goes around.
    It can be seen clearly in the gif
     
  2. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    71
    Joint stores a target angular offset and use it to solve the constraint.

    The problem is because the Transform.rotation is actually stored with quaternion for 3D.
    Since 2d physics only handle with the single float as rotation, Unity did it by converting the quaternion rotation to euler angle and extract the z axis as 2d rotation.
    The converting only occurs when transform "sync" to rigidbody, and the sync happens iftransform was changed.

    The converting could make the angle of rigidbody 2d lose if the angle is out of -180 or 180 which causes this problem.

    For example, there are two rigidbodies A and B with rotation 180 and 90 and a joint to constraint them with -90 angular offset, meaning (B's angle - A's angle) = -90.
    Then A rotates to 181 degree by changes rotation in transform (modified in editor).
    Since the transform changed, physics 2d would sync the transform to rigidbody.
    Pass through converting from quanternion to euler, the 181 degree becomes -179 degree.
    Now A is -179, B is 90, and the joint's target angular offset is -90 still. physics engine will calculate as B should rotate to -269 to fit constraint.

    The idea is if you want to use joints which considered angular, you should not directly modified the rigidbody's transform to prevent from syncing.
    Unity did something I don't know inside the physics engine to make the rigidbody somehow don't wrap into -180 ~ +180 degree if there is any joint considered of angle. But it will mess up if transform sync to rigidbody.
     
    MelvMay and dikar771 like this.
  3. dikar771

    dikar771

    Joined:
    Oct 30, 2015
    Posts:
    19
    Thanks for the answer! Just tried it with AddTorque and rigidbody.rotation and everything works fine, but I think I'd got this issue in my game project where all rigidbodies controlled via rigidbody.rotation. But there are more complex chaints of joints, I'll try to localize it futher.
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    Yes the simple rule is that you should never modify the Transform to move anything related to physics. No exceptions. If you have an argument to do so then you're into undefined and potentially unstable territory. The solver will do its best but you're fighting against it at that point.

    The primary role of the Rigidbody2D is to be the authority on position and rotation (pose) and writes that to the Transform. Modifying the Transform bypasses it and instantly updates (Teleports) the body. We have to then jump through hoops trying to catch up to this distruptive change. Joints are particular sensitive to this.

    You should always move using the API provided on the Rigidbody2D but understand, physics wants to move with linear and angular velocity. Setting an instant position/rotation via the Rigidbody2D is still teleporting. To ensure you're using velocity, you can use MovePosition an MoveRotation.
     
    dikar771 likes this.