- Home /
Problem Understanding Quaternions
I'm trying to get my head around what exactly Quaternion.LookRotation does since the documentation is vague.
If I create a zx (horizontal) ground plane and create a stick like game object on it (like a clock hand) I can easily get that stick to face a target pos using:
Vector3 toTarget = target.transform.position - transform.position;
Quaternion newRot = Quaternion.LookRotation(toTarget, Vector3.up);
transform.rotation = newRot;
This makes sense since I'm reading that function (perhaps incorrectly) as rotating the stick around the up vector to face in the direction of toTarget.
If I create an xy (vertical) plane and position a stick on it I'd expect to be able to rotate that stick by using this:
Vector3 toTarget = target.transform.position - transform.position;
Quaternion newRot = Quaternion.LookRotation(toTarget, Vector3.forward);
transform.rotation = newRot;
Alas that does all sorts of weird stuff. The stick is rotated along all axis instead of just the the z axis. I can correct it by setting the x and y components of newRot to zero before applying it to the transform but I don't understand why i should have to -- why it should behave differently to the first example.
I've searched around a bit but I cannot find anything that explains what's happening here. Can someone help me?
Answer by Bunny83 · Jun 25, 2011 at 12:42 PM
LookRotation will always rotate the object into the direction you give. The upvector just specifies where the y-axis will point to. You're not rotating around the upvector, you're rotating around the look-vector. I'm not sure where your target is. if it's on the plane it should work your way. You may invert the Vector3.forward vector if the stick is rotated around the lookvector by 180°. Also it would be better to use a vector from the plane space as up vector. Use .forward / .up / .right of the planes transform.
edit
Where does the local axis of your plane point at? If you use the default plane that comes with Unity the face will look at the local up vector (y-axis)
If you use the plane's upvector as upvector it should work, no matter how you rotate your plane as long as the target is on the plane.
Transform target; // assign the target object
Transform plane; // assign the plane
void Update()
{
Vector3 toTarget = target.position - transform.position;
Quaternion newRot = Quaternion.LookRotation(toTarget, plane.up);
transform.rotation = newRot;
}
Right. You have to understand that when an object is rotated to look at something, it's local z-axis will point it it. But it's head can still be rotated 360 degrees around that axis (upside down for instance) so you have to specify what the local y-axis should be.
If an object is already rotated to have his head 'up' (local y-axis alligns with the planes local y-axis) and you give it a target on that plane, then I expect it will rotate the way you expected.
Hi Guys,
Thanks very much for your quick answers. I'm still really struggling with this though.
The target is on the same plane as the stick.
Bunny83: what is the 'look-vector'? Is that the toTarget value in my example? If it is then I don't understand why you say the object is being rotated about it. In the horizontal plane example the rotation is around the y-axis until the object's facing vector aligns with toTarget.
Can you provide me with the code I would need to use to rotate an object with local y-axis pointing up, about the z-axis to face a target position? (like looking at a clock face on a wall and rotating one of the hands to face a numeral) That might help me see it more clearly.
You have to think 3 dimentional. LookRotation will rotate the local z-axis at the given target. That's the look direction. It will always point exactly at the target. The rotation around the local z-axis is subsidiary. It will rotate the object that it's local y-axis (up) will point "in the direction of the given upvector" but not necessarily exactly because the direction to the target is the primary direction. If your given upvector is exactly perpendicular to your look direction it will match the y-axis.
I'll add an example
Yeah I was also struggling to understand what would happen if the two were not perpendicular. Turns out the 'looking' is the important one, and if the 'up' one isn't perpendicular it just picks on that's close.
I'm starting to see it now.
Bunny: I'd still like to see your example code for the clock example above if you have the time.
Thanks a lot guys.
Answer by aldonaletto · Jun 25, 2011 at 02:30 PM
When you assign a new rotation to a transform, it replaces the original one. If the object was originally rotated in order to face what you consider its forward direction, then assigning a new rotation will make it loose the original setup, and it will be left looking to the wrong side. If this is the case, you should save the initial rotation in Start, then always multiply this rotation to the new one before assignment:
Quaternion rot0;
function Start(){
rot0 = transform.rotation;
}
// apply the new rotation combined with the original one:
transform.rotation = rot0 * newRot;
NOTES:
1- Quaternion operations aren't commutative: don't change the order, or you can have weird results.
2- I'm a JS guy, thus forgive me for any eventual C# error.
3- More details about quaternion multiplication at: http://unity3d.com/support/documentation/ScriptReference/Quaternion-operator_multiply.html