Explanation Of Vector3.Cross With Quaternion.LookRotation

Cross-posted from Unity Questions, since I’ve gotten no replies there.

Hoping someone can explain the math behind this:

I am working on a survival game and needed to rotate walking animals to match the slope of the terrain under them without affecting the direction they were pointing. IE, they needed to rotate in the local Y axis, without affecting their local X and Z axes.

After a lot of searching and trouble I came across this code:

RaycastHit hit;          
         if(Physics.SphereCast(transform.position, 0.5f, -(transform.up), out hit, yourDistenceToGroundYouWant, yourGroundLayers))
         {
          transform.rotation = Quaternion.LookRotation(Vector3.Cross(transform.right, hit2.normal)
         }

It’s on this thread, for some context: Rotating a player to match terrain slope - Questions & Answers - Unity Discussions

It was practically a 1 to 1 drop in to my own script, resulting in this:

RaycastHit hit;          
if (Physics.Raycast(transform.position, -Vector3.up, out hit))
{
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(Vector3.Cross(transform.right, hit.normal)), .01f);
}

Now, no complaints from me and I’m really grateful to @Fanttum for the answer, but what is bothering me is that I don’t know WHY this code does what it does. Quaternions are mystery oil to me; could someone spread some enlightenment here, so I’m not just another copy-paste-codemonkey in this regard?

Thanks!

Vector3.Cross(transform.right, hit.normal)

When you cross product two Vectors, you get a resulting Vector which is perpendicular to both of these. This results in either a Vector pointing in either the forward or backward direction in which we want our object to face. Which one depends on the order of the cross product, but in this case, it’s the forward.

Quaternion.LookRotation(vector)

This just turns our resulting vector into a Quaternion. Since there’s no second optional parameter, according to the documentation, it gives us a Quaternion rotation where our object is facing in the correct forward pose, with up, being up.

So, if I understand this correctly:

This code is using Vector3.Cross to compare the transform’s current “rotation.x” and the normal’s “rotation.y” and generate a new Vector3. IE, it effectively “levels” the transform around it’s own “X” in reference to the ground’s “UP” direction. As a result of comparing the two Vectors, it effectively reorients the animal’s “UP” without affecting or referencing it’s rotation around that same axis?

Calling them rotations is incorrect, as they’re Vectors, which is a rotation with a distance, but in this case the distance does not matter.

If you call transform.right, it will return a Vector pointing in the direction of the object’s right. For example, if you called Transform.right on an object with no rotation, it would be (1, 0, 0), but if you called it and it was turned around, it would return (-1, 0, 0). A normal also returns a Vector, not a rotation value. A normal is the vector pointing directly away from the surface, usually (0, 1, 0) when from a flat ground.

1 Like