I am trying to implement animation mirroring for a character model. The model uses an hierarchy of bones and has a skinned mesh. The models original orientations and having to deal with a hierarchy of bones gave a lot of headache while implementing the mirroring, but in the end I managed to get it working.
To change the animation dynamically I change the rotation and position of bones in the LateUpdate function of a script that is placed on the same object that has the SkinnedMeshRenderer placed on it. I almost have the mirroring of the character working. However there is a one problem I am unable to solve.
At some point during the mirroring of the animation, the root bone (in top of the hierarchy) suddenly flips/snaps making my character model twist badly in the area of the root bone. The root bone is even rotating in the wrong direction at some point.
In my script I calculate the new rotation of each bone and the rotation I calculate is correct. However when I apply this rotation to the bone, it is changed into another rotation by Unity. An example would be (pseudo code, but actual values from Debug.Log):
Vector3 mirrRot = new Vector3(267.4f, -232.4f, 189.8f); // correct mirrored rotation
Quaternion mirrored = Quaternion.Euler(mirrRot); // create a quaternion using the correct euler rotation
// lets see what the actual rotation of the root bone looks like
Debug.Log(mirrored.eulerAngles);
// mirroring should be applied over (270, 90, 0) as this is the original bone orientation
// unmirrored value: (272.6, 52.4, 189.8)
// expected value: (267.4, -232.4, 189.8), note that -232.4 equals 127.6
// actual result: (272.6, 307.6, 9.8), output of the Debug.Log statement above
I guess there is some quaternion magic happening here. I suspect something like (x, y, z, w) becoming (-x, -y, -z, -w) or something like that. The expected euler rotation and the actual euler rotation might be the same (I’m unsure tbh). However it totally ruins the model (causing a twist and a rotation in the wrong direction) while animating it.
All other bones in the hierarchy are working perfectly fine and are mirrored as expected (but this might be pure luck of course ;-)).
I also tried throwing overboard the euler angles and doing the entire calculation with quaternions. However the problem was exactly the same. Does anybody have a clue how I would be able to fix this? Is there any way to let Unity use the exact euler angles I calculated (and about which I know they are correct)?