Search Unity

RelativeJoint2D. angularOffset and linearOffset changing with script

Discussion in 'Physics' started by IamProt, Dec 9, 2015.

  1. IamProt


    Dec 9, 2015
    Hello to everyone.
    I am tried to use new joint, but right here stumble across strange things.
    First, I tried ti change angularOffset and linearOffset by script. It work, but work very strange. I wanted to switch joint between 2 states. So I took parameters from component in both situations and make simple script:
    Code (CSharp):
    1. private Transform drone_transform;
    2. private RelativeJoint2D ClawL_joint;
    3. private RelativeJoint2D ClawR_joint;
    4. private bool Claws_dir = true;
    5. private bool Claws_on = false;
    6. private Vector2 ClawL_open_vector = new Vector2(-0.07617173F, -0.3821043F);
    7. private Vector2 ClawL_closed_vector = new Vector2(0.2374096F, -0.3089377F);
    9. void Start()
    10. {
    11. drone_transform = GetComponent<Transform>();
    12. ClawL_joint = drone_transform.transform.Find("ClawL").gameObject.GetComponent<RelativeJoint2D>();
    13. ClawR_joint = drone_transform.transform.Find("ClawR").gameObject.GetComponent<RelativeJoint2D>();
    14. }
    15. void Update()
    16. {
    17. if (Input.GetKeyDown(KeyCode.Space))
    18. {
    19. Claws_on = true;
    20. }
    21. }
    23. void FixedUpdate () {
    25. if (Claws_on == true && Claws_dir == true)
    26. {
    27. Claws_on = false;
    28. Claws_dir = false;
    29. ClawL_joint.angularOffset = -0.507531F;
    30. ClawL_joint.linearOffset = ClawL_open_vector;
    31. }
    33. if (Claws_on == true && Claws_dir == false)
    34. {
    35. Claws_on = false;
    36. Claws_dir = true;
    37. ClawL_joint.angularOffset = 0.3444556F;
    38. ClawL_joint.linearOffset = ClawL_closed_vector;
    39. }
    41. }
    But it move joined object different way it should. And, what even more strange, when I manually enter same numbers during playback, there are different result then it done by script.
  2. alanic



    RelativeJoint2D is indeed strange... Because it's buggy.

    Bug1: In an older Unity version (I think 5.3.3) reading angularOffset would give degrees but writing expected radians. So, even doing rb.angularOffset = rb.angularOffset would make it turn like crazy. Judging by the date of your post, your version probably had that bug. However, you are writing in radians, so this bug was probably not biting you. Now in 5.3.5 it's all degrees. So, your code with radians would fail big time with 5.3.5 right now.

    Bug2: What RelativeJoint2D tries to do in the angular sense is to ensure rbOther.rotation - rb.rotation = angularOffset. In the process, it ignores all kinds of modulo 360 issues. angle1 and angle1+360 are actually the same angle and for most cases we shouldn't differentiate between the two. RelativeJoint2D does differentiate between the two in a buggy way. If all you are doing is to rotate your object by incrementing rb.rotation, you won't see a bug with RelativeJoint2D. In almost all other rotation cases (including 2D hinge joint motors), rb.rotation will sometimes switch between angle and angle+360. When it does the switch, RelativeJoint2D will do a full flip. Therefore, at every frame, you should ensure that rbOther.rotation - rb.rotation = angularOffset is not going to cause a full flip. You can do this by doing something along the lines of rb.rotation = rb.rotation + 360 when necessary.

    I created a RelativeJointCompanion component that ensures that RelativeJoint2D runs perfectly. This took me a while to figure out... If there is interest, I can put it on GitHub.