Can someone please explain the difference between TransformPoint and InverseTransformPoint?

I’ve read a few different posts about this on StackOverflow and the Unity forums, but I still don’t understand what’s happening with these functions. Let me attempt to briefly explain what I do think I understand about transforms in Unity. I’ll keep things simple by pretending we’re in 2D using an empty GameObject (this way we don’t have to take into account any scaling).

“World” space is the space relative to the world axis. World space should be constant throughout the project because the world space does not change. The origin of the world is at position (0, 0) in the world. If something is at position (0, 1) in world space, it will be 1 unit above the world origin.

“Local” space is the space that is relative to a GameObject. Essentially, the “origin” of the local space is the GameObject’s center. So, if a GameObject’s center point is at point (5, 5) in the world, any new objects transformed around it locally will be transformed around this point; in other words, we can think of (5, 5) as the center of the “world” of that GameObject. If I wanted to have a new object be 1 unit above this GameObject, it would be at position (6, 5) in the world, but would be at position (0, 1) in local space.

Hopefully I’m correct about that stuff, but if not I welcome any clarification. Here’s some code (I will now be using two 1x1 boxes):

public class GreenBox : MonoBehaviour
{
    [SerializeField] private GameObject redBox;

    private void Update()
    {
        redBox.transform.position = new Vector2(2, 0);

        Vector2 position = new Vector2(0, 1);
        position = redBox.transform.TransformPoint(position);

        transform.position = position; // Move the green box to "position"
    }
}

Transform.TransformPoint “transforms position from local space to world space;” in my code, “position” is the new Vector2(0, 1). This is what results if I move the redBox to position (2, 0) in world space:

If I use the same code, but switch to redBox.transform.InverseTransformPoint(position) (which says that it “transforms position from world space to local space”), and keep the redBox at position (2, 0) in the world, this is what happens:

Based on the descriptions of these methods, I have no idea what’s going on with my short block of code. I don’t understand how, in the case of Transform.TransformPoint, my “position” of (0, 1) is transformed from local space to world space (which is supposed to be constant throughout the world) by being above the redBox at all times; wouldn’t that be local? Likewise, it seems that InverseTransformPoint is sort of a mirror image of the world space position of the redBox; I thought that this method would behave as the first one does, since it transforms a point in world space (0, 1) to local space (the position of the redBox). I understand that these methods are being called from the transform of the redBox, but it just doesn’t make sense to me.

Am I doing something wrong? Any help would be appreciated!

If you run this code;

[SerializeField] GameObject someObject;

void Start()
{
    // Instantiate an object to the right of the current object
    Vector3 thePosition = transform.TransformPoint(2, 0, 0);
    Instantiate(someObject, thePosition, someObject.transform.rotation);

    // Instantiate an object to the right but inverted of the current object
    Vector3 theInversePosition = transform.InverseTransformPoint(2, 0, 0);
    Instantiate(someObject, theInversePosition, someObject.transform.rotation);
}

You’ll see that Transform.TransformPoint does is add the position of the transform and thePosition together, which explains your green box being at the position of the red box plus the position you gave it.

Transform.InverseTransformPoint subtracts the position of the transform and then adds the theInversePosition. resulting in your green box first going from 0,0 to -2,0 and then adding the 0,1 .Takes some getting used to.