localPosition vs Position Subtraction as vector direction

What is the difference between local position and world position difference?


For context, I have object B as children to object A

I’d like to keep object B near object A forward position using the algorithm below.


// Update


// var bVector = B.localPosition.normalized // this behaves strangely
var bVector = (B.position - A.position).normalized; // this works

var viewAngle = Vector3.Angle(A.forward, bVector);
var axis = Vector3.Cross(bVector, A.forward).normalized;

if (Mathf.Abs(viewAngle) > _limitViewAngle)
{
                    transform.RotateAround(A.position, axis, 30f * Time.deltaTime);
}

I think that it’s strange that the line above doesn’t work.

Shouldn’t subtracting B position with A position makes it a relative position which is the same as local position?

Note: I don’t have scale on both object A and B.

Well basically the name says it all. One is the local position/rotation, one is the global. The only difference is the so called “frame of reference”. For global positions and for objects without a parent this global frame of reference is the general global coordinate system. All positions and rotations are given in relation to the global origin.

You might notice that A.localPosition and A.position is the same since A does not have a parent. (Well that is my assumption at least)

When you have a parent to an object (like in your example B is child of A) then B has a set of local coordinates with is different to the global ones.

the local coordinates and global coordinates are linked by the parents rotation and position:

  B.position == B.localPosition * Quaternion.Inverse(A.rotation) + A.position

So this means:

Asuming we set B on the local position Vector3.forward and A on [1, 0, 1] with A.rotation = Quaterion.identity then Bs global position is [1, 0, 2]

If we now rotate A around the zAxis then the local Position of B would not change.

The global position of B would be:

  B.position == A.position + [cos(zAngle), -sin(zAngle), 0]
  where
  [cos(zAngle), -sin(zAngle), 0] is another way to write B.localPosition * Quaternion.Inverse(A.rotation)

I can only recommend to read a bit into rotation matrices. Intresting topic and helps understand a lot.

So when you take the above the yes your lines

var bVector1 = B.localPosition.normalized // this does not work
var bVector2 = (B.position - A.position).normalized; // this works

are indeed not the same vector as bVector1 will always be the same vector in local coordinates which you then would try to compare to vector A.forward which is in global coordinates - so in a different frame of reference.

You can make it work with local coordinates if you change this

 var viewAngle = Vector3.Angle(A.forward, bVector1);

to

  var viewAngle = Vector3.Angle(Vector3.forward, bVector1);

At this point you might see that this value that you calculated all the time between (B -A) and A.forward is actually constant if the local coordinates of B do not change.

Hope this helps. Let me know if something was not clear.