This must be some obvious thing I’m doing wrong or some quirk I’m unaware of. I have three objects:
MyMesh
1.1 ReferenceImages (nested under MyMesh)
1.1.1 ImagePlaneRight (nested under ReferenceImages)
All have scale 1,1,1, except ImagePlaneRight, which is 0.2,0.2,0.2.
All have 0 rotation, except ImagePlaneRight, which is 90,0,-180.
All have a localPosition set to something nonzero.
I’m calling transform.InverseTransformPoint(position) from a script on ImagePlaneRight. The resulting position is totally bogus. Here’s a log example:
Here, return is the result of InverseTransformPoint. I expect it to be very close to localPosition, because the world position I’m converting is colliding with ImagePlaneRight.
Is there something I’m not understanding about InverseTransformPoint? Are there situations in which it will not give correct results? I’m using Unity 5.5.0f3.
If you run InverseTransformPoint it will take the input Transform Position from world space and give you its position relative to the Transform it was called from so your result is totally dependent on where you have placed the Transform you’re calling it from.
And here is the output from the Log statements:
UpdateLocalPositionFromWorldPosition newWorldPosition=(0.3, 1.9, -1.5),localPosition=(0.0, 0.0, -1.5),transform.InverseTransformPoint=(-0.6, 0.1, 0.5)
expectedLocalPosition=(0.3, -0.1, -1.5)
You asked about the expected result. Apparently I get the expected result when I set: transform.position = newWorldPosition
I don’t understand the difference between that and: transform.localPosition = transform.InverseTransformPoint(newWorldPosition)
Shouldn’t they do the same thing?
Your transform stack is more than one level deep, so its only local to the first parent. If the grandparent is also a non-zero position then it adds to the offset.
Ok. So I can’t trust transform.InverseTransformPoint(newWorldPosition) when my object is nested more than one level? What’s the appropriate way to translate a world position to a local position in that case?
Just set the world position of the object instead, don’t even bother with the whole localposition mess. It’s still a child, so once it moves to that world position it will continue to behave normally (move/rotate by its parent etc).
So, when I need a localPosition, I shouldn’t use transform.InverseTransformPoint(newWorldPosition). I should set the position to the newWorldPosition and just read localPosition.
That’s… awkward. What if I need more than one localPosition in order to perform a calculation? Wouldn’t it be inefficient to move the object twice rather than calculate the position twice?
Before you use localPosition, you should ask why do you even need the local position? More importantly, why would you need the localPosition of two objects with completely different parents? That is an extremely obscure relationship.
“Awkward” would be localPosition returning the position relative to the uppermost grandparent, making it obscurely difficult to retrieve the much more commonly required local position relative to the first parent. In the majority of cases the world position can be used for calculations between objects and it will be more efficient than using localPosition and a bunch of InverseTransform methods. Even then if you had to structure it in such a way, the performance impact would be basically too miniscule to note
I use localPosition anytime I want to think about position without relation to the world. My app is a VR vertex modeler so I tend to use localPosition to describe a vertex’s position in relation to the mesh origin. Also, snapping tends to be in relation to the local space rather than the world too.
If transform.InverseTransformPoint(newWorldPosition) doesn’t work reliably below X levels of nesting, it should say that in the documentation.
It gives you the position of itself relative to its parent. That is literally what it’s scope is. It sounds like you’re expecting it to do something outside that scope.
All it says is “Transforms position from world space to local space.” There’s no mention of nesting issues.
I have no problem with localPosition. It works fine. My issue is that transform.InverseTransformPoint(newWorldPosition) doesn’t reliably transform a point from world space to local space.
I think you’re actually misunderstanding what “Transforms position from world space to local space.” actually means.
Not that it’s not reliable.
It IS reliable.
It’s reliable at giving the result as defined, not the result you expect.
You seem to be expecting a completely different functionality.
Give you an example.
TransformPoint takes a point in local space and makes it global. So if you had a Mesh on a GameObject, and that GameObject was nested in other gameobjects, that had scales and rotations on them, so on and so forth.
Then you accessed the ‘vertices’ of the Mesh, those vertices are in local space.
If you call TransformPoint on a vertice using the Transform of the gameobject it’s attached to. You’ll get the position of that vertex in world space.
on the flip side
InverseTransformPoint would take that resulting world space position, and return the position it would be as a vertex in the mesh.
This takes into consideration, all translations (positions), rotations, and scaling.
Because InverseTrasnformPoint takes into consideration the transform you’re attached to.
localPosition is relative to the PARENT, not to itself. If it was relative to itself, setting it to the value <1,0,0> would move it 1 down the x-axis over and over every time you set it.
That’s what I want it to do, but that’s not what it’s doing. I’m not sure why. I’m starting to think it’s a bug in this case as no one is pointing out why it’s happening.