Place child GameObject at absolute world position

I’ve been developing in Unity for years and I can’t believe I’m stumped by something that should be very simple. I want to instantiate a GameObject and place it at a world position but I also want to parent it to a twisted mess of a tree of GameObjects (all different rotations/scales of the objects in the tree). Seems simple enough. The Unity Editor can figure it out. I can spawn the object but not parent it, run it in the editor, hit pause and then drag the GameObject to the node I want and, lo and behold, it stays put.

But programmatically? That’s been a nightmare. I’ve tried setting the parent transform right IN the Instantiate call. I’ve tried transform.SetParent() with a true for keepworldposition. I’ve tried TransformPoint. I’ve tried a half dozen other things besides this too, and the object keeps moving on me. I do not know the relative position for that complex transform but I also don’t want the GameObject to not be parented because I want it deleted when the root is deleted.

Is it even possible to parent a GameObject to somewhere in the bottom of a twisted mess of an object tree but make sure it starts off at an absolute world position? Of course I don’t care that the object would move with the parent. In fact, the parent won’t be moving. I can’t even set it’s initial position properly.

EDIT

This does appear to be broken in that version of Unity. I suggest you report it as a bug and roll back to a previous version

EDIT B

On testing it seems to be fixed in the last LTS version and the latest non LTS versions. So it is likely that it is just this version that has this problem.


transform.position = new Vector3(...)


Description: The world space position of the Transform. The position property of a GameObject’s Transform, which is accessible in the Unity Editor and through scripts. Alter this value to move a GameObject. Get this value to locate the GameObject in 3D world space.



I’m not sure what the confusion is here, you can always set its position relative to the world. If its un-parented and you parent it (I think) it retains its position in world space it just updates its local space coordinates relative to its hierarchy.

Video

sacredgeometry, I don’t see my most recent comment in the hierarchy above. If I click “Show More Comments”, it stops with your comment about testing with other values. Does answers.unity.com have the same problem as GameObjects’ positions?? LOL But I didn’t see that comment until I wrote this whole thing but I’ll post it again anyway. Thanks for looking into it :slight_smile: Yeah, it’s very counterintuitive behaviour.

Here’s my original reply that is disappearing:

Thanks for even testing it in my version. I hope you didn’t have to download it just for that quick test.

This is SO weird. Here’s my code:

 var bobber=(GameObject)Instantiate(Resources.Load("bobber"));
 //        bobber.transform.position=pos;
 bobber.transform.parent=fish.line.transform;
 bobber.transform.position=pos;

//old code, tried it this way too…

// var bobber=(GameObject)Instantiate(Resources.Load(“bobber”),pos,Quaternion.identity,fish.line.transform);

So, if I simply instantiate the object on its own and set it to the calculated position it needs to be it, it stays at: 2783.991f, 175.7f, 4639.482f (the correct location;) But parenting it to my hierarchy moves it to: 2809.843f, 170.3355f, 4645.75f Well, the position in the editor showed a local position so I hit pause, dragged it out to the root and then copied down this position.

This is driving me crazy. I have no scripts that are altering this object’s position after the fact. Are you aware of anything that could be in the hierarchy of objects I parented it to that could throw off setting transform.position? I know you don’t know my hierarchy (it’s a UMA character’s bones), but can you think of anything that can throw off Unity’s transform.position function?

I appreciate all the help you’ve given me.

I fixed this by having the bobber on the end of my fishing line be a separate, unparented entity and keeping a reference to it in a data structure so I can kill it when the line disappears.

There is either a bug in all recent versions of Unity (at least since 2018) or object.transform.position isn’t meant to set a child object to an absolute position in the world. The final position is influenced by all of the scales and rotations in the hierarchy of parents, parents of parents, etc, under which the object sits. The only solutions are to keep the object at the very top-level (global level), parented to an object at 0,0,0 scale 1,1,1 rot 0,0,0, or to parent it to the root of your object as long as that object doesn’t move or turn, of course (which was my case).

The is the only acceptable answer so far. I jumped the gun on accepting the other answer but he was extremely helpful and very appreciated.

I know this quite late, @ChristmasEve or anyone is still facing this issue, What i noticed is that if you set the relative world position of the child object in the same frame it is parented, then for some unknown reasons, it snap to another position.

The solution is obviously to parent the object in a frame and set its world position in the next (or one of the successive frames), either with a coroutine or an Invoke (with a delay). Although the object does flicker in that frame (if its in view of the camera) due to unity first setting its position to a (random i guess) position and you are resetting the object back to where you want it to be. A quick work around for this is to duplicate the object and disable the original (to keep the visual), parent the original, then after resetting the original’s position, enable it back and discard the duplicate.

 Transform myChildobj, myParentObject;
    
    IEnumarator ParentChild(){
    Vector3 childOriginalWorldPos = myChildobj.position;

    // to keep the visual if it's within the camera's view
    GameObject duplicate 
     = Instantiate(mychildobj,mychildobj.position,mychildobj.rotataion).gameObject; 

    //you can disable the renderer instead
    myChildobj.gameobject.SetActive(false); 

    //you can use setParent as well with true or false
    myChildobj.parent = myParentObject; 

    yield return null; // to wait for the next frame
    myChildobj.position = childOriginalWorldPos ;
    Destroy(duplicate);
    }