Why can't I set transform.position on a child object?

In code, I can set the transform.position on a game object and see the result in game.

In the editor, I can set the position of an object, and then set the object as a child of another. When I do this, the position values displayed are changed to localPosition equivalents that keep the object in the same place in space, which makes sense. This made me presume that something analogous would happen when working in code.

However, if there is a transform.parent of an object, setting the transform.position yields no result in game. The debugger seems to confirm that the transform.position assignment is undone after parenting, or the assignment is ignored if it’s already parented.

I can get around this by using math relative to the local space and setting the transform.localPosition on the child object. I was just wondering if anyone knew what was going on here. Is transform.position effectively read only for getting child object global position? Does Unity actually have global position assignment silently fail for child objects? Am I misunderstanding things?

Some examples:

Setting relative position works for child:

bar.transform.parent = transform;
bar.transform.localPosition = new Vector3(0f, 0f, 1f);
Debug.Log("local position: " + bar.transform.localPosition);  // 0, 0, 1

Setting global position works for unparented object:

bar.transform.position = new Vector3(0f, 0f, 1f);
Debug.Log("global position: " + bar.transform.position);     // 0, 0, 1

Setting global position for child doesn’t work:

bar.transform.parent = transform;
bar.transform.position = new Vector3(0f, 0f, 1f);
Debug.Log("global position: " + bar.transform.position);   // 0,0,0

Setting global position for unparented object works, but is undone when parented:

bar.transform.position = new Vector3(0f, 0f, 1f);
Debug.Log("global position: " + bar.transform.position);  // 0,0,1 applied
bar.transform.parent = transform;
Debug.Log("global position after parenting: " + bar.transform.position); // 0,0,0 again

transform.position refers to the Transform’s global position.

transform.localPosition refers to the Transform’s position relative to it’s parent.

I’ve created an empty gameobject at 10,0,0 and attached a new c# script with your code. When i execute the scene i get:

bar's global position: (0.0, 0.0, 1.0)

When i select the child object in the inspector it shows the correct local position of

(-10.0, 0.0, 1.0)

which equals the world position (0.0, 0.0, 1.0)

Have you actually tested your example?

If i move the parent to 0,0,0 i also get the same output.

The only way i can get your output is when the parent objects scale is set to 0,0,0. In this case all child objects have to be at the parents origin since it’s not possible to calculate a localPosition inside a zero-space.