I'm trying to have one object match another object's rotation delta. So if object A rotates 90 degrees around Y axis I want object B to also rotate 90 degrees around Y axis. Since I want to do it every frame, I save the initial rotations of both objects. I tried doing it like this, based on this forum post:
objectB.transform.localRotation = (initialObjectARotation * Quaternion.Inverse(objectA.transform.localRotation)) * initialObjectBRotation;
The issue is that now the rotation is inversed (I'm not sure this is the correct term, but if I rotate objectA
right then objectB
rotates left etc.). How can I fix this?
If you have the absolute rotation of B (the subject doing the matching) and A (the target being matched) from the previous frame and the new absolute rotation of A, you can solve for the new absolute rotation of B interpreting the A difference along the local axes of each object:
Quaternion oldB; // previous global rotation of subject
Quaternion oldA; // previous global rotation of target
Quaternion newA = transformA.rotation; // current global rotation of target
// solve for new global rotation of subject
Quaternion newB = oldB * Quaternion.Inverse(oldA) * newA;
If that gives you results you don't like you could try interpreting the diff along global axes:
// solve for new global rotation of subject
Quaternion newB = newA * Quaternion.Inverse(oldA) * oldB;
Finally, if you really want it relative to the axes of each object's parent, it's a bit more complicated because it involves the previous parent rotations (absolute), the previous local rotations of the objects, and the current absolute rotation of A to give you the current absolute of B. :
Quaternion oldBParent; // previous global rotation of subject's parent
Quaternion oldBLocal; // previous local rotation of subject
Quaternion oldAParent; // previous global rotation of target's parent
Quaternion oldALocal; // previous local rotation of target
// solve for new global rotation of subject
Quaternion newB = oldBParent * Quaternion.Inverse(oldAParent) * newA
* Quaternion.Inverse(oldALocal) * oldBLocal;
Note that if there is no parent, then the parent rotations are Quaternion.identity
and it is equivalent to the global axes form. Neat!
And of course once you have newB
, you only need to apply the new rotation with transformB.rotation = newB;
.