- Home /
How to change game object's parent in hierarchy without changing it's transform's position?
When we move a game object to be child of another game object in hierarchy, Unity changes it's transform position so that the game object can maintain it's global position in the world.
I think it's a pain to always reset and/or recalculate positions when moving a game object in hierarchy so I want to know if there's a simple/easier way to do this: move the game object so that it can maintain it's LOCAL position. As if we were just writing transform.parent = parentGameObject.transform
via scripts.
For example:
EmptyObjectP1
position is(0, 0, 0)
EmptyObjectP2
position is(10, 0, 0)
EmptyObjectChild
is currently child ofEmptyObjectP1
and it's position is(2, 0, 0)
Now, if we move
EmptyObjectChild
to become parent ofEmptyObjectP2
, it's position will change to(-8, 0, 0)
and it will stay in the same position(2, 0, 0)
in the world. I want it to stay(2, 0, 0)
so that it's global position change to(12, 0, 0)
get the localPosition of the child
store value in temporary variable
change the parent
set the localPosition to the stored variable
Answer by AlucardJay · Apr 21, 2014 at 02:00 AM
Here are a couple of scripts to add this functionality in Edit mode. In the Editor folder, add the script ObjectMoverInspector. You can place the script ObjectMover anywhere (in a folder called Helpers for example). Yes, I have awesome naming conventions =]
If the new menu item doesn't appear, just reopen the project. Then you can select Custom > Object Mover. This creates an empty object in the scene with the script ObjectMover attached. Drag and drop your child and new parent object in the Inspector then click the button.
ObjectMoverInspector.js
#pragma strict
@CustomEditor( ObjectMover )
class ObjectMoverInspector extends Editor
{
var childToMove : SerializedProperty;
var newParent : SerializedProperty;
var obj : GameObject;
var objScript : ObjectMover;
function OnEnable()
{
obj = Selection.activeGameObject;
objScript = obj.GetComponent( ObjectMover );
childToMove = serializedObject.FindProperty( "childToMove" );
newParent = serializedObject.FindProperty( "newParent" );
}
function OnInspectorGUI()
{
// Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
serializedObject.Update();
// childToMove
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField( childToMove );
EditorGUILayout.EndHorizontal();
// newParent
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField( newParent );
EditorGUILayout.EndHorizontal();
// Editor GUI Buttons
EditorGUILayout.BeginHorizontal();
if ( GUILayout.Button( "Reparent and position", GUILayout.MinWidth( 80 ), GUILayout.MaxWidth( 250 ) ) )
{
objScript.ChangeParentAndReposition();
}
EditorGUILayout.EndHorizontal();
// Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
serializedObject.ApplyModifiedProperties();
}
}
@MenuItem( "Custom/Object Mover" )
static function CustomObjectMover()
{
var go : GameObject = new GameObject( "_ObjectMover" );
go.transform.position = Vector3.zero;
go.transform.rotation = Quaternion.identity;
go.AddComponent( ObjectMover );
}
ObjectMover.js
#pragma strict
public var childToMove : Transform;
public var newParent : Transform;
private var localPos : Vector3;
private var localRot : Quaternion;
function ChangeParentAndReposition()
{
if ( !childToMove || !newParent )
{
Debug.LogWarning( "Assign Objects in Inspector" );
return;
}
Debug.Log( "Change Parent And Reposition" );
localPos = childToMove.localPosition;
localRot = childToMove.localRotation;
childToMove.parent = newParent;
childToMove.localPosition = localPos;
childToMove.localRotation = localRot;
}