Transform.parent doesn't work correctly

When setting the position and parent of a gameobject via script, I’ve hit a problem that doesn’t occur when doing the same thing via the editor: if the gameobject is a child of an object which is the child of another (i.e., if the parent is itself a child), then the position is always screwed up after using transform.parent to define the parent (e.g., ThisObject.transform.parent = OtherObject.transform). This only retains the correct position if the parent isn’t a child, otherwise the end result is always offset incorrectly because it doesn’t seem to take the entire hierarchy into account when calculating the localPosition - i.e. it seems to calculate the local position only based on the immediate parent rather than the entire chain, so the final position is wrong. But for some reason. this is never a problem when setting the parent via the editor, since it always seems to work correctly regardless of the hierarchy structure.
The only way I’ve found to get around this problem is to set the parent first and then manually calculate the correct offset, then use ThisObject.transform.localPosition = (offset). This is frustrating, because my older code is set up to do it the other way, since it used to work when each object only had a single parent in the chain.
Is there any other way to fix this problem?

That sounds right to me … local position should only be relevant to the zero point of parent above in the chain … that is what local means :wink:

Try create a test scene project or perhaps just explain with a detailed example using numbers etc as to where you think there is a fault in the system. Maybe I did not understand your problem exactly.

Here’s an example:
In one case, I use code to set the top-level parent gameobject to a position of (-80.36923, -1233.965, 4265.16) and then I create another gameobject and give it the same position, then make the first the parent of the second using code with the form: SecondGO.transform.parent = FirstGO.transform; but when I look at these gameobjects in the editor, the 2nd has a relative position in which the sign has been reversed for each coord (80.36923, 1233.965, -4265.16), and so the absolute position is always 0 rather than the correct position, with the result that the 2nd object doesn’t show up in the correct place. If I do the parenting in the editor, however, then the result is always correct : the relative position is 0 and the absolute position is (-80.36923, -1233.965, 4265.16) , and the 2nd object shows up in the proper place.

here is a script to test :

Just create a blank scene with one cube at pos 0,0,0 and attach this script , I made my cube material alpha 50% so I could see the duplicate in the same position , I set the camera to pos 0,0,-6.

• run the game
• click duplicate
• click parent
• check console debug info

everything is as expected. I dont usually check things in the editor when testing my game builds but did so this time to validate and the positions were correct there as well … no incorrect offsets.

I did notice one quirk though … if you highlight the duplicated cube in the inspector it seems the transform component displays the local position values now … I guess that can cause some confusion but regardless of that - all positions are in the right place in the game and the editor window and the debug info also reveals that all local and global positions are correct via code.

using UnityEngine;
using System.Collections;

public class TestCubeParenting : MonoBehaviour {

	public Transform cube;
	private Transform cube2;
	private Vector3 testPosition = new Vector3(2,2,2);
	
	public void Start(){
		cube = transform;
		cube.position = testPosition;
	}
	
	void OnGUI() {
        if (GUI.Button(new Rect(10, 10, 150, 50), "duplicate")){
            cube2 = Instantiate(cube,cube.position,cube.rotation) as Transform;
			
		};
		if (GUI.Button(new Rect(10, 60, 150, 50), "parent")){
            cube2.parent = cube;
			Debug.Log("cube 2 localPosition: "+cube2.localPosition);
			Debug.Log("cube 2 Position: "+cube2.position);
			
		};
        
    }
	
	
}

now that I think of it , I dont even think there is a quirk at all … the inspector transform component always displays local position values! So even if I had to manually drag and drop the cube to make it a parent in the editor I would expect the same results as the code…

and here it is straight from the Unity documents to confirm :