In one of the videos of the dead earth game dev series , the author mentions of calculating a local desired velocity of a NavMeshAgent.

My point of confusion was, wasn't the desired velocity local to begin with? From the docs, it's given that desired velocity is:

The desired velocity of the agent including any potential contribution from avoidance. (Read Only)

since the agent is dynamic shouldn't the velocity already be calculated in the agent's local space, I thought so atleast because it would make sense because most useful case for us is to calculate a certain angle based on the orthogonal vector of one of the axes of the agent's local space and the desired velocity for which desired velocity should be in local space?

And, then he converts the desiredVelocity to local space of the agent by doing transform.InverseTransformVector(desiredVelocity). It's using this means that there's an inverse transformation matrix cached by unity. Since, the navAgent is dynamic, it's origin moves about, i.e. the local space moves about as well. So, does that mean the inverse of the transformation matrix from world to local space is calculated for each frame?

EDIT: Consider the following diagram: enter image description here There are two vector spaces here, 1) The world space(w-space), and 2) the agent space(a-space). So, (a, b) in w-space is (c, d) in a-space, and so on.

So, this I faintly recall is a problem related to change-of-basis of vector spaces? The transformation between these spaces should be guide by a transformation matrices say M, assuming both these spaces are orthogonal, and the bases for each is of unit length, the transformation composition is typically: M=TR, where T is a transformation matrix and R is a rotation matrix.

Now, the question is, if (a, b) in w-space is equal to (a, b) in a-space, then T should be an identity matrix, which means no transform.InverseTransformVector(....) should be required at all, since there's no translation at all, but, if it is required, then what is the translation? And as you demonstrate in your code that it could just be an inverse-rotation, then, why the need to convert it into localspace at all? It could just be the inverse-rotation in world space itself.


1 Answer 1


Velocities in Unity are almost always in world space coordinates. So unless you see something that specifically promises you a local space velocity, world space should be your default assumption. This is the easiest coordinate system to use for handling interactions with objects outside this single entity (like the navmesh, or collisions).

On the occasion when you want to do computations on the velocity relative to the agent's facing direction - as is the case in this tutorial - you can convert the velocity into local coordinates using InverseTransformVector or InverseTransformDirection, as demonstrated in the source you're referencing. That gives you a version of the velocity in the agent's local coordinate system, making it easy to compute the angles as you describe.

using this means that there's an inverse transformation matrix cached by Unity

No, that is not an absolute requirement. I'd argue what you really want here is InverseTransformDirection, which can be implemented as simply as this:

Vector3 InverseTransformDirection(Vector3 input) {
    // This is 3 multiplications, not a full matrix inverse.
    Quaternion q = Quaternion.Inverse(this.rotation);
    return q * input;


Since the NavMeshAgent is dynamic, its origin moves about.

That does not matter when we're transforming offset vectors like directions, displacements, or velocities - note how the example function above does not use the origin at all. We only need the origin when we're transforming points / position vectors.

So, does that mean the inverse of the transformation matrix from world to local space is calculated for each frame?

Not necessarily. It could be computed only when something changes, or only on demand, or not computed at all if the route Unity uses does not include a matrix, like the example above. What matters here is that the API gives us ways to move vectors between coordinate systems on demand - the details of how the engine facilitates this should not matter. It's not our responsibility.

  • \$\begingroup\$ by offset vectors, do you mean direction vectors? it doesn't seem to be a standard term. \$\endgroup\$
    – BumbleBee
    Commented Nov 16, 2021 at 16:40
  • \$\begingroup\$ An offset is a difference between one value and another — like a displacement from position A to position B. \$\endgroup\$
    – DMGregory
    Commented Nov 16, 2021 at 16:51
  • \$\begingroup\$ above you mention having inverse matrix cached is not a requirement and inverse is simply 3 multiplications, which means like rotating -30 is the inverse of rotating 30 degs? but, this kind of transformation is legal only when the origins coincide, isn't it? but the navmesh agent has it's origin at (x, y) which may not be (0,0) worldspace, right? how does that make sense? \$\endgroup\$
    – BumbleBee
    Commented Nov 16, 2021 at 17:13
  • \$\begingroup\$ I'll repeat: the origin is never used in this calculation. It is not part of the problem we are solving. There is no matrix that can even contain origin information in the code I showed, only a quaternion which represents rotation alone. It has no concept of translation in space, because we do not need it. \$\endgroup\$
    – DMGregory
    Commented Nov 16, 2021 at 17:14
  • \$\begingroup\$ I don't know if my confusion is from euclidean geometry that I'm familiar with, not very much with quaternions. But, linear transfm stuff should be translatable in both forms of rotation, let me sketch a diagram to clarify myself, just a sec..... \$\endgroup\$
    – BumbleBee
    Commented Nov 16, 2021 at 17:24

You must log in to answer this question.

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