About Transform.TransformDirection()

Hi everyone,

We have a cube game object and the script is attached to this cube.

You draw a ray using:
Debug.DrawRay(transform.position, Vector3.Forward);
This code draws a ray that faces the world z direction. If you rotate the cube the ray does not rotate with it. The ray still faces the world z direction.

You then draw a ray using:
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.foward));
This code draws a ray that faces the cube’s z direction. If you rotate the cube, the ray rotates with it.

It looks like Transform.TransformDirection() transforms a world direction into a local direction.

However when you look at Unity scripting API definition of Transform.TransformDirection, it says:
Transforms “direction” from local space to world space.

It sounds like the API definition says the oppositite of what the code does.

Can anybody explain this ?

Thank you.

Hi Guybrush,

In which course and lecture are you?

Hi Nina,

This is Complete C# Unity Game Developer 3D > Introduction to Raycasting.

Instead of Physics.Raycast, I used Debug.DrawRay to see the ray. And instead of FPCamera.transform.forward, I used Vector3.forward.

transform.Translate(Vector3.forward) moves your object moves in its local z direction. However Debug.DrawRay(transform.position, Vector3.forward) draws the ray in the world z direction. In order to draw the ray in the object local z direction (as opposed to world z direction) you need to use transform.TransformDirection. But the API defines TransformDirection as turning a world direction into a local direction, which looks like the opposite of what it does. That seems confusing to me.

I hope I was clear in explaining the confusion.

Thanks for your help.

Thank you for the explanation.

The Unity API is known for being limited and confusing. Since most parts of Unity are not open-source, we do not know what is going on behind the scene in most cases. This means that I cannot explain any differences between the implementation of Unity code and definitions/descriptions in the API. There might be mistakes, or there is a misunderstanding.

“Transforms direction from local space to world space” (source) is not necessarily wrong. DrawRay probably refers to the world space coordinate system.

Each game object has got its own local coordinate system which is relative to the parent game object (or origin of the World Space if there is no parent). If the game object is rotated by, for example, 90° on the x-axis, its local axes are not aligned with the World Space axes anymore.

That’s the only explanation for the behaviour you described that comes to my mind.

Thanks for your help Nina.

If DrawRay refers to world space then TransformDirection, which by definition transforms from local to world, transforms from world to local in this case, I guess :slight_smile:

transforms from world to local in this case

How did you figure that out, by the way? Did you log the result into your console and compared it with the values of the local “forward” axis?

In your initial post, you wrote:

Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.foward));
This code draws a ray that faces the cube’s z direction. If you rotate the cube, the ray rotates with it.

From what I understood, your description matches the description in the API.

The DrawRay method uses a starting and a target point in World Space coordinates to draw the ray. Vector3.Forward is defined as (0, 0, 1). If you draw a line from (0, 0, 0) to (0, 0, 1), that line aligns with the global z-axis.

If you rotate the game object at (0, 0, 0) by 90° around its y-axis, its local “forward” axis points to (1, 0, 0), which matches the global x-axis. The definition of Vector3.forward did not change, though; it is still (0, 0, 1). The ray aligns with the global z-axis and the local x-axis of the rotated game object.

If you rotate the game object and want to align the ray with a specific axis “controlled” by the game object, you have to rotate the ray along with the game object. Remember DrawRay still refers to World Space coordinates. This means that the new target point should be (1, 0, 0), not (0, 0, 1). Fortunately, you don’t have to do the maths yourself because Unity provides a method for you: TransformDirection.

Test that with Debug.Log to see if I’m right.

Hi Nina,

Thanks a lot for your detailed response.

Yes

Yes

Yes, TransformDirection does this. However, what confuses me is its API definition. From our conversation we both agree that TransformDirection takes a world space coordinates and turns it into local space. Otherwise to ray does not rotate along with the game object. Yes?

But the API definition of TransformDirection says that it “transforms direction from local space to world space.”

I totally understand what TransformDirection does in this case but it does not seem to match its API description.

Um, actually, I tried to explain why it is not “world space > local space” but the other way round. transform.TransformDirection(Vector3.forward) interprets Vector3.forward as the local “forward” vector. That local vector gets converted to the global vector.

In this context, (0, 0, 1) refers refer to the local coordinate system of the game object. That local coordinate system might be rotated relative to the origin of the World Space coordinate system.

That’s why you call TransformDirection. If it converted the global Vector3.forward coordinates (0, 0, 1) to a local variable, you would have to convert the result to global coordinates because:

The DrawRay method uses a starting and a target point in World Space coordinates to draw the ray.

Not local coordinates.

I would recommend to log the values into your console to see what you get during runtime. Without knowing the actual values, the whole concept remains a mere theory. And a theory is basically fantasy, which may or may not match reality.

Ok, I will log the values to see what happens during runtime.

Thanks a lot Nina :+1:

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.