Reputation: 11319
This is the code for replacing :
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();
}
}
I'm selecting this door the door is inside a space station and the door is a child of another gameobject and the other gameobject is also child :
Then I have a prefab I want to replace it with the door : The prefab is the same door I just changed the two doors in the middle made them in red but the prefab is just a door like in thecfirst screenshot. Same size scaling :
Then when making the replacing the prefab is places in a bit back from where the door was position but in the inspector I see same position as the door :
Now the prefab is positioned much to the back inside the room. If I change the position and rotation in my code to local then the prefab will be positioned to much forward. It will never position at the place of the door.
I tried other replace scripts all give the same result/s. I didn't change anything in the prefab(The prefab is a door) only add this colors.
Upvotes: 0
Views: 488
Reputation: 86
This is happening because the center of the prefab is different than the original object's center.
You can recenter object by putting it in a empty object and moving it in the local position of that object.
Then you can use that object as the prefab that is going to be in the scene.
Hope it helped
Upvotes: 1