- 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
Follow this Question
Related Questions
Why is rotation locking to an axis? 3 Answers
AddForce to transform.up locks ship at 90/270 degrees (gimbal lock?)... 1 Answer
Just updated to 2017.3.0f3 And my moving platforms are locking my character's rotation 1 Answer
rotate a object around the x axis like other object... stucks at 90 degrees 2 Answers