Hi there, I’m working on a lovely little duplicator tool.
The main idea is that it can be used together with Snaps (Asset Store) to create prototyping environments even faster!
Unfortunately, I still have one issue with prefabs I can’t seem to resolve.
What happens is that I am instantiating the Prefab via PrefabUtility.Instantiate, which doesn’t copy any overrides (under which the Transform override).
This won’t do. When I use duplicate (Ctrl + d) on a prefab, all of the instances overrides are carried over as you’d expect. This is what I need! Is there any way to access that behaviour via code? I’ve already scoured the docs on PrefabUtility, but the documentation there is lacking a bit, and the documentation on UnityEditorInternal is non-existent. I’m kind-of out my debt on this, I’m not someone to post needlessly.
For good measure, here is the code I use to instantiate the new objects (the translation equals the offset from the original source).
void InstantiateObjects(Vector3 translation)
{
foreach(var gameObject in TargetQuery)
{
GameObject go = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
if(go)
{
go = PrefabUtility.InstantiatePrefab(go, gameObject.transform.parent) as GameObject;
}
else
{
go = GameObject.Instantiate(gameObject, gameObject.transform.parent);
go.name = gameObject.name;
}
go.transform.Translate(translation, Space.World);
Undo.RegisterCreatedObjectUndo(go, "Created Object");
}
}
Quick update, I have now solved part of this issue doing this:
...
GameObject go = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
if(go)
{
go = PrefabUtility.InstantiatePrefab(go, gameObject.transform.parent) as GameObject;
PrefabUtility.SetPropertyModifications(go, PrefabUtility.GetPropertyModifications(gameObject));
}
...
This will copy all the property modifications (like transform.position & MeshRenderer.MotionVectors) but NOT added and removed components (like Mesh Collider and Thing) in the above example.
Unfortunately, this is the only Set() method that PrefabUtility has, and GetObjectOverrides() doesn’t include added and removed components.
I will use GetAdded- and GetRemovedComponents() and loop through these, but I still don’t believe you don’t support copying a prefab as an instance. I believe that is something Unity should manage.
For anyone looking for a code snippet, this is roughly what I used to duplicate a prefab instance in the Unity editor, preserving not only PropertyModifications, but also added GameObject(s) and Component(s).
I had to send the “Duplicate” event to the Hierarchy View (where you see your Transform hierarchies in the editor).
The Hierarchy View is where I usually go select objects, and press Ctrl + D to duplicate them.
The code below does exactly this:
using System;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
public static class EditorWindowUtil {
//This method finds the first EditorWindow that's open, and is of the given type.
//For example, this is how we can search for the "SceneHierarchyWindow" that's currently open (hopefully it *is* actually open).
public static EditorWindow FindFirst(Type editorWindowType) {
if (editorWindowType == null)
throw new ArgumentNullException(nameof(editorWindowType));
if (!typeof(EditorWindow).IsAssignableFrom(editorWindowType))
throw new ArgumentException("The given type (" + editorWindowType.Name + ") does not inherit from " + nameof(EditorWindow) + ".");
Object[] openWindowsOfType = Resources.FindObjectsOfTypeAll(editorWindowType);
if (openWindowsOfType.Length <= 0)
return null;
EditorWindow window = (EditorWindow) openWindowsOfType[0];
return window;
}
//Works with prefab modifications, AND added GameObjects/Components!
//The PrefabUtility API does not have a method that does this as of Unity 2020.1.3f1 (August 24, 2020). For shame.
public static GameObject DuplicatePrefabInstance(GameObject prefabInstance) {
Object[] previousSelection = Selection.objects;
Selection.objects = new Object[] { prefabInstance };
Selection.activeGameObject = prefabInstance;
//For performance, you might want to cache this Reflection:
Type hierarchyViewType = Type.GetType("UnityEditor.SceneHierarchyWindow, UnityEditor");
EditorWindow hierarchyView = EditorWindowUtil.FindFirst(hierarchyViewType);
//Using the Unity Hierarchy View window, we can duplicate our selected objects!
hierarchyView.SendEvent(EditorGUIUtility.CommandEvent("Duplicate"));
GameObject clone = Selection.activeGameObject;
Selection.objects = previousSelection;
return clone;
}
}
now it’s addressable objects.
unity needs to have an easy way for duplicating, saving, loading, move on grid prefabs in the stage and editor.
I need to use addressable that forces me to go online.
if I want stand-alone I need to use the JSON utility for saving but not vector3 or quaternions
I need to create a class for it and then break apart the x y z into an array.
why ?
because simple JSON that supported JsonArray is gone.
I mean … common … unity expects from people that want to create to go through havoc.
unity needs to provide simple scripts that will function like components.
they need to have a pool of them and we just need to drag and drop in the inspector.
for example, save load, grid, color picking, dragging, etc… and all the expensive and elementary assets that people buy from the unity store.