This site uses strictly necessary cookies. More Information

X- Home /

# Gimbal lock when only modifying 1 axis

I am currently facing the gimbal lock problem.

My target:

During animation, apply the half of the local rotation of X in RightHand to RightForeArmTwist, where the local rotation of Y,Z of RightForeArmTwist is keeping the same.

Here is part of the structure of my model:

Root

|-...

|-RightForeArm

|-RightForeArmTwist

|-RightHand

The image above is the parameters of Righthand and RightForeArmTwist when the model is in T pose.

When animation played, the rotation value of RightForeArmTwist is not what I want, and made the model broken.

What I expected is the local rotation of RightForeArmTwist is [-2.535, -2.255, -180].

```
[SerializeField]
Transform rht_hd;
[SerializeField]
Transform rht_farmtwist;
Vector3 twistR_default = Vector3.zero;
void Start() {
twistR_default = rht_farmtwist.localRotation.eulerAngles;
}
void LateUpdate() {
rht_farmtwist.localRotation = Quaternion.Euler(rht_hd.transform.localRotation.eulerAngles.x * -0.5f, twistR_default.y, twistR_default.z);
}
```

Any suggestion in solving the gimbal lock problem?

**Answer** by unity_ek98vnTRplGj8Q
·
Mar 11, 2020 at 03:03 PM

First of all, this is not gimbal lock. Gimbal lock is when the first two rotations using euler angles cause the 3rd axis of rotation to line up with one of the previous two axis, effectively cutting off motion in the 3rd axis. More than likely you are experiencing another issue to do with euler angles, which is that for any given rotation there are many different sets of euler angles that describe that rotation.

When you put rotation angles into the inspector, Unity automatically converts these angles into a Quaternion internally. When you go back to read these angles in code, there is no guarantee that the angles it gives back are the same ones that you plugged in. This can also lead to what *I think* is the issue that you are experiencing, which is taking an euler angle out of context. Euler angles are nice to read when you have relatively simple rotations about 1 or 2 axis, but an euler angle read from a more complex rotation only makes sense *in context with* the other angles. For example, you may look at an object and it looks like it has a large angle of rotation in the z axis, and you are probably correct that there are some sets of euler angles that have a large z value for that rotation, but there is no guarantee that Unity returns one of these sets of angles.

So how do you fix your problem? I think "apply the half of the local rotation of X in RightHand" is not really what you want to do, as just plugging in an existing angle into an entirely different rotation is bound to cause trouble. Perhaps if you could describe *functionally* what you want to have happen, then we could find a better approach, however currently it is hard to help as I believe your description of your desired result is slightly flawed

Thanks you for reply and sorry for the misunderstanding of Gimbal lock.

In my current project, I am migrating an existing App, develop by other engine and about 10 years ago, to Unity.

Currently, we already have more than thousands of motion FBX, and several models with completely same skeleton to motion files.

What I currently do is that during the motion animation is playing, the "RightForeArmTwist" bone will act as an auxiliary bone to simulate the muscle movement for the ForeArm.

In the existing app, it used a simply idea that the "ForeArmTwist" just follow the X rotation of "Hand" in which the value is half.

An now I want to do the same in Unity, but facing the above problem.

Hmm this interesting... I'm no quaternion master no solution pops out at me immediately. Can you Debug.Log the default angles as well as the final calculated rotation angles for those same inspector values? Something seems off to me about this

Here is the script:

```
public class BoneFix : $$anonymous$$onoBehaviour
{
[SerializeField]
Transform lft_hd;
[SerializeField]
Transform lft_farmtwist;
[SerializeField]
Transform rht_hd;
[SerializeField]
Transform rht_farmtwist;
Vector3 twistL_default = Vector3.zero;
Vector3 twistR_default = Vector3.zero;
Quaternion twistL_default_q = Quaternion.identity;
Quaternion twistR_default_q = Quaternion.identity;
[SerializeField]
bool isSupport = true;
// Start is called before the first frame update
void Start()
{
twistL_default = lft_farmtwist.localRotation.eulerAngles;
twistR_default = rht_farmtwist.localRotation.eulerAngles;
twistL_default_q = lft_farmtwist.localRotation;
twistR_default_q = rht_farmtwist.localRotation;
}
private void LateUpdate()
{
fixBoneRot();
}
public void fixBoneRot()
{
if (isSupport)
{
lft_farmtwist.transform.localRotation = Quaternion.Euler(lft_hd.localRotation.eulerAngles.x * 0.5f, twistL_default.y, twistL_default.z);
Debug.Log("RightHand: x: " + rht_hd.localRotation.eulerAngles.x + ", y: " + rht_hd.localRotation.eulerAngles.y + ", z: " + rht_hd.localRotation.eulerAngles.z);
Debug.Log("Default: x: " + twistR_default.x + ", y: " + twistR_default.y + ", z: " + twistR_default.z);
rht_farmtwist.transform.localRotation = Quaternion.Euler(rht_hd.localRotation.eulerAngles.x * -0.5f, twistR_default.y, twistR_default.z);
Debug.Log("Twist: x: " + rht_farmtwist.transform.localRotation.eulerAngles.x + ", y: " + rht_farmtwist.transform.localRotation.eulerAngles.y + ", z: " + rht_farmtwist.transform.localRotation.eulerAngles.z);
}
}
}
```

And Here is the Debug.Log:

```
For T-pose
RightHand: x: 1.207419E-06, y: 356.1887, z: 3.180554E-15
Default: x: -2.760866E-16, y: 357.745, z: 180
Twist: x: -6.037096E-07, y: 357.745, z: 180
```

```
For Play animation in 58 Frame
RightHand: x: 354.9293, y: 353.7413, z: 12.36512
Default: x: -2.760866E-16, y: 357.745, z: 180
Twist: x: 357.4647, y: 177.745, z: 5.007481E-06
```

Also, I found that the animation curve for the hand is different from $$anonymous$$aya after imported to Unity.

Unity:

$$anonymous$$aya:

You may have a look on the "Purple" Curve in Unity, and compare it to the "Red" Curve in $$anonymous$$aya. I do not know if this would cause the problem.

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.