Unity3D HingeJoint2D reference angles and setting rotation in script.

This article was born from tracking down an issue (Unity Bug #712007) when setting the rotation of RigidBody2D objects connected with a HingeJoint2D in Unity3D version and 5.1.1p4

I detail how the angle limits work, a potential pitfall when setting rotation on disabled objects and finally detail the spinning issue and a solution we can use until the issue is fixed.

Reference Angle & Joint Limits

It’s important to note that we are using angle constraints where we specify the range of angles the hinge is allowed to be.

TestHinges_2_unity_-_TestHinge2D_-_PC__Mac___Linux_Standalone

Unity does this by first defining a reference angle. You can read the reference angle from the HingeJoint2D but can not set it. So what is it and how is it defined?

First notice that the hinge joint gizmo shows a green line, this is defined by the x axis of the object that the hinge joint is a component of.

TestHinges_2_unity_-_TestHinge2D_-_PC__Mac___Linux_Standalone

 

If we print out HingeJoint2D.referenceAngle for the above we get -17°. Looking at the inspector of the root it has a rotation of -15° and the child a rotation of -32°, so the reference angle is the difference between the rotations of the objects but when?

The simplest answer is it’s when the objects Start would be called, ie the first frame they are active but only then not on subsequent enable / disables.

There is a bit more to it though; the child object must be active when the hinge is enabled. If not, and later  you enable the child, the joint will have no affect on the child until you disable and re-enable the joint or edit other parameters such as motors / limits etc. This may be a bug in Unity, it’s easy to work around though ensure you enable and disable the hinge joint along with the child it connects to.

The unexpected turn

In some scenarios we need to setup the position and rotation of certain bodies. For example setting up a rag-doll to follow on from an animated character, or just initialising a physics model to a pre-recorded settled state. I found that occasionally a certain joint would rotate and end up in an unexpected orientation.

After considerable experimenting I eventually managed to recreate the issue 100% in a simple example. In the below gif both bone hierarchies appear to be the same, looking in the inspector they have the same rotations, angle limits and reference angle.

SpinRotate2

As you can see the right hand hierarchy does not fall as expected, instead it begins to rotate.

To look into this further I displayed the Euler angles followed by Quaternion components for the root and child and you can see that both objects start with the exact same orientations. Looking in the scene view you can see the reference line that Unity draws for the hinge gizmos is within the limits but the second set of bodies decides to rotate round the external part of these limits until it is again within them.

Turn2Now look at the white number inside the root object this is what HingeJoint2D.JointAngle is returning. So for some reason Unity has calculated an angle outside of the 360 degree range and rotates the objects to within the hinge limits.

The setup

As I mentioned the scenario when this occurs in game is when I copy rotations from a RigidBody2D to another in the rag doll. I know the angles are all within the limits already.
In the below test case I have two rag doll setups Source1 and Source2 which appear to be the same in the transform inspector but on printing their quaternions you will note that the quaternion of the source2 root is the negative version of source1. (0.0, 0.0, 0.1, -1.0)

In the video below I first copy source 1 and source 2, if I were to unpause at that stage the copies would do exactly the same as the originals suggesting that the negative quaternion isn’t a problem in it’s self but maybe used during the initialisation of the joint or something.

I then copy the local position and rotation from the orientation objects shown top right. Un-pausing after this then shows up the issue.

You can download the above test project here: TestHinge2D

Initial solution

My initial solution to this was to ensure that all bones in my rag doll had positive w in the quaternion and when I copy the rotations to the rag doll I negate them if necessary to ensure that they too have positive w. This solved my initial problem.

Additional Limbs

During gameplay my character has his left legs and arm disabled since they would be hidden by the right counterparts, it being a 2d side on game. However when the character crashes I enable these limbs and copy the orientation and position from the right parts.

In this scenario ensuring the quaternions had positive w did not solve the issue if the character had been rotating. When that occurs their bodies can gain negative w quaternions, which is no bad thing and I felt from above that what was important was the starting sign.

I’ve not worked out how to fix this occurrence of the issue yet or how to reproduce it in a simple test scene.