How can I place a prefab in another gameobject place with the same center ?

I have this door and it’s center is : 23.1, 52, -6

And then when replacing a prefab instead this door the prefab center is 20.9, 52, -6
The result is that the prefab placed a bit in the back from the door position and if I’m using local in my script the prefab will be position a bit to the front position from the door position.

It will show that the prefab is at the same position as the door was but since the center is not the same it will not place the prefab at the right position.

This is the prefab after replaced instead the door:

And this is my code. I wonder how can I keep or set the prefab center to be like the door center through the code :

Or if I need to do it once in the editor using a empty GameObject and then make a prefab from the empty GameObject then how do I make it in the editor ? I didn’t understand if the prefab should be child of the empty gameobject ? And then how to set the empty gameobject to be in the right center of the door ? And then the prefab child what position should he be ?

Maybe someone can draw it visual to show how to do it ? I didn’t understand.

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class SaveTransformsInfo : EditorWindow
{
    [SerializeField] private GameObject prefab;

    [MenuItem("Tools/Replace With Prefab")]
    static void CreateReplaceWithPrefab()
    {
        EditorWindow.GetWindow<SaveTransformsInfo>();
    }

    private void OnGUI()
    {
        prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);

        if (prefab == null || Selection.gameObjects.Length == 0)
        {
            GUI.enabled = false;
        }
        else
        {
            GUI.enabled = true;
        }
        if (GUILayout.Button("Replace"))
        {
            var selection = Selection.gameObjects;
            var parentGameobjects = CheckParents(selection);

#if UNITY_EDITOR
            UnityEditor.Selection.objects = parentGameobjects;
#endif

            for (var i = parentGameobjects.Length - 1; i >= 0; --i)
            {
                var selected = parentGameobjects[i];
                var prefabType = PrefabUtility.GetPrefabType(prefab);
                GameObject newObject;

                if (prefabType == PrefabType.Prefab)
                {
                    newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                }
                else
                {
                    newObject = Instantiate(prefab);
                    newObject.name = prefab.name;
                }

                if (newObject == null)
                {
                    Debug.LogError("Error instantiating prefab");
                    break;
                }

                Undo.RegisterCreatedObjectUndo(newObject, "Replace With Prefabs");
                newObject.transform.parent = selected.transform.parent;
                newObject.transform.position = selected.transform.position;
                newObject.transform.rotation = selected.transform.rotation;
                newObject.transform.localScale = selected.transform.localScale;
                newObject.transform.SetSiblingIndex(selected.transform.GetSiblingIndex());
                DestroyObjectInPrefab(selected.transform);
            }
        }

        if(GUILayout.Button("Get Info"))
        {
            TransformSaver.SaveTransform(null, Selection.gameObjects[0]);
        }

        GUI.enabled = false;
        EditorGUILayout.LabelField("Selection count: " + Selection.gameObjects.Length);
    }

    private GameObject[] CheckParents(params GameObject[] objects)
    {
        List<GameObject> parents = new List<GameObject>(objects.Length);
        Transform[] transforms = objects.Select(go => go.transform).ToArray();
        for (int objectIndex = 0; objectIndex < transforms.Length; objectIndex++)
        {
            if (!IsChildOfAny(transforms[objectIndex], transforms))
                parents.Add(transforms[objectIndex].gameObject);
        }

        return parents.ToArray();
    }

    private bool IsChildOfAny(Transform potentialChild, params Transform[] potentialParents)
    {
        for (int index = 0; index < potentialParents.Length; index++)
        {
            if (IsParentOf(potentialParents[index], potentialChild))
                return true;
        }
        return false;
    }

    private bool IsParentOf(Transform potentialParent, Transform potentialChild)
    {
        if (potentialChild.parent == null)
            return false;

        if (potentialChild.parent == potentialParent)
            return true;

        return IsParentOf(potentialParent, potentialChild.parent);
    }

    private void DestroyObjectInPrefab(Transform transform)
    {
        if (PrefabUtility.IsPartOfPrefabInstance(transform))
        {
            //if a part of a prefab instance then get the instance handle
            Object prefabInstance = PrefabUtility.GetPrefabInstanceHandle(transform);
            //destroy the handle
            if (prefabInstance != null)
            {
                Undo.DestroyObjectImmediate(prefabInstance);
            }
        }
        //the usual destroy immediate to clean up scene objects
        //DestroyImmediate(transform.gameObject, true);
        Undo.DestroyObjectImmediate(transform.gameObject);
    }

    private void OnSelectionChange()
    {
        Repaint();
    }
}

When you create a prefab, make sure its center is a the base. Then align objects in prefab. After than, when you drop you prefab at floor position, all object should be positioned correctly.

1 Like