This question is related to my previous post here , but, even though I did get some insight, I didn't fully get it, and hence have another dilemma. Since the dead earth series is not publicly available, I'll try to explain as much as possible.

Initial around 21:35 timecode of the lesson 13 of the series, the author tries to find the direction the navMeshAgent should turn. For this, he applies the sign of the cross product between desiredVelocity vector and the local z-axis of the navMeshAgent. If the result was negative, he turns left, if positive he turns right. Note that here, he does not convert the desiredVelocity vector to the navMeshAgent's local space.

But, later, we come to a case where we require the angle between the desiredVelocity vector and the navMeshAgent's local z-axis. In this case, he does convert the desiredVelocity vector to the local space of the navMeshAgent using transform.InverseTransformVector(desiredVelocity). I don't really get the concept behind it. Why are we not converting the desiredVelocity vector to localSpace in the former case? Obviously the direction might change from conversion of one space to another, so the result should be affected. Please help me understand this. Thanks in advance.


1 Answer 1


This is all about apples to apples comparisons and what's the path of least resistance to the information we want.

When we just want to know whether one vector in the horizontal plane is to the left or right of another, checking the sign of the cross product is a nice quick way to do that, at just six multiplications and three subtractions — less than a matrix multiplication or quaternion rotation. (In fact, since we only care about the sign of the y component in that case, we can do it with two multiplications and a comparison — though the compiler might or might not figure out that optimization for us)

We could do this equally well in either world space or local space, since we'll get the same output vector either way, just expressed in a different basis. Since transform.forward already gives us the object's forward direction in world space, we can just use the world space velocity directly with that and not do any space conversions. So here, world space is the path of least resistance.

When we want to know the specific angle between two vectors, that can get a bit trickier. If we normalized the velocity first we could use the arcsine of the length of the cross product, but that's two square roots and divisions plus a transcendental, and it can give incorrect results if our vectors are not perfectly in-plane (say the velocity is tilted slightly uphill — we'd get an angle in a tilted plane instead of the pure horizontal angle we might expect)

But if we could express the velocity as a direction relative to the object's orientation, then we could use the convenient 2-argument arctangent function to get the exact planar angle we want. And here again, Unity offers a convenient path to get there with transform.InverseTransformVector, which provides exactly the needed transformation. Now we have the velocity in a coordinate scheme where z+ is the object's forward and x+ is its right, and finding the turning angle is as easy as expressing that vector in polar coordinates. So here, local space gives us the path of least resistance to what we want.

Note that if we need to do both in a single function, then we might as well use the latter trick with local space. That will get us both the angle and its sign at once. But if we're doing them separately, and either the velocity or the orientation may change in between, then using the shortest route to each data point makes sense.

The tutorial may also be deliberately trying to show you a variety of ways to find out about vector angles, to build up your toolbox.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .