When I duplicate an object in the scene hierarchy, the newly created object gets sent all the way to the bottom of the list of objects. Then I have to drag it all the way back up to be next to the object I duplicated, since usually I want to group them together. Is there a way to duplicate it so it gets put next to the object I’m duplicating automatically?
I loved this question! You made my day dude!
You can write custom scripts for Unity Editor, for more information: Unity - Scripting API: MenuItem
And this is simple code, that will allow you Duplicating selected GameObject, and instantly making it as a child! Is that great, isn’t it? I love Unity! And i added Shortcut for you, just select GameObject and tap CTRL+SHIFT+D , bingo!
using UnityEditor;
using UnityEngine;
public class UnityAnswers_CustomUnityEditorDuplicator : MonoBehaviour {
[MenuItem("Editor Extensions/Duplicate Selected and make it as a child #%d")]
static void DoSomethingWithAShortcutKey()
{
Object prefabRoot = PrefabUtility.GetPrefabParent(Selection.activeGameObject);
if (prefabRoot != null)
PrefabUtility.InstantiatePrefab(prefabRoot);
else
Instantiate(Selection.activeGameObject, Selection.activeGameObject.transform.position, Selection.activeGameObject.transform.rotation, Selection.activeGameObject.transform);
Debug.Log("Sir, i duplicated and made it as my child!");
}
}
Hello,
Can you modify the script so the duplicate is STILL a instance of a prefab?
If so,
Thanks a Bunch!!!
and Sorry, posted this as an answer.
Combining ideas from How do I properly duplicate an object in a editor script? - Questions & Answers - Unity Discussions (general duplication) and answers here (setting sibling index), I wrote an editor script that supports working in Prefab edit mode and increments the suffix number based on the current Numbering Scheme setting.
I copied the script below but really, Unity Answers is not fit for those long scripts, I think a forum thread would be better (esp. if we bring gradual improvements). I don’t see such a thread on Unity forums right now, so I’ll just be posting here for now, but if myself or one of you wants to bring further improvements to it, I suggest we open a new thread on the forums and put them there.
In the meantime, I’ll put a link to my public repo so there is always the latest version: Bitbucket
and the current script as of 2022-05-10 below so it’s accessible directly on this page:
// DuplicateGameObjects.cs
// References:
// - ReplaceGameObjects.cs in same folder for prefab linking and support for additive scenes
// - https://answers.unity.com/questions/168580/how-do-i-properly-duplicate-an-object-in-a-editor.html
// (Anisoropos's answer)
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
public static class DuplicateGameObjects
{
[MenuItem("Edit/Duplicate Below %#d", priority = 120)]
private static void DuplicateSelectionBelow()
{
PrefabStage currentPrefabStage = null;
// Check current stage
Stage currentStage = StageUtility.GetCurrentStage();
if (currentStage is PrefabStage prefabStage)
{
// Prefab edit mode
currentPrefabStage = prefabStage;
}
else if (currentStage is not MainStage)
{
// Not Prefab edit mode nor Main scene, must be a custom stage
Debug.LogWarning("Duplicate Below is not supported in custom stages");
return;
}
var clones = new List<GameObject>();
// Note that Selection.transforms, unlike Selection.objects, only keeps the top-most parent
// if you selected both a parent and a direct or indirect child under it.
// But since duplicating children modifies the parent content, it means that we would get different results
// when duplicating the parent or the child first, so it's more stable to just ignore children.
// "Prefab Mode in Context" pseudo-game-object is also ignored by Selection.transforms,
// unlike Selection.objects, so it's safer on that side too.
foreach (Transform selectedTransform in Selection.transforms)
{
GameObject selectedGameObject = selectedTransform.gameObject;
if (currentPrefabStage != null && selectedGameObject == currentPrefabStage.prefabContentsRoot)
{
// Prefab root is selected in Prefab Stage
// In a prefab, we cannot duplicate the root under itself, since it must have no siblings,
// so skip it. And since Selection.transforms ignores children, we know it's the only selection,
// so just break.
break;
}
// Get new game object name following Project Settings > Editor > Numbering Scheme
string newGameObjectName = GameObjectUtility.GetUniqueNameForSibling(selectedTransform.parent,
selectedGameObject.name);
GameObject clone;
// Support prefab instances
GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(selectedGameObject);
if (prefab != null)
{
// Create another prefab instance under same parent as duplicated object
// The stage will be set later with PlaceGameObjectInCurrentStage, the parent can still be set now.
// If working on the Main Stage, the scene will also be set later with MoveGameObjectToScene,
// so don't bother passing the Scene instead of the parent Transform when selectedTransform.parent
// is null.
clone = (GameObject)PrefabUtility.InstantiatePrefab(prefab, selectedTransform.parent);
PrefabUtility.SetPropertyModifications(clone, PrefabUtility.GetPropertyModifications(selectedGameObject));
}
else
{
// The duplicated object is not a prefab, create a standard clone under the same parent
clone = Object.Instantiate(selectedGameObject, selectedTransform.parent);
}
// Place clone in current stage
// This only matters when editing in Prefab Mode
StageUtility.PlaceGameObjectInCurrentStage(clone);
// When selected object is at scene root (only possible in Main Stage, not Prefab Stage,
// since we do nothing in case root is selected, but checking it just in case),
// it will be placed in the active scene by default, so move it to the same scene as the selected object
if (currentPrefabStage == null && selectedTransform.parent == null)
{
SceneManager.MoveGameObjectToScene(clone, selectedTransform.gameObject.scene);
}
// Move clone right under selected object
// This works even with multiple selection under the same parent as GetSiblingIndex is reevaluated
// after the last child insertion
clone.transform.SetSiblingIndex(selectedTransform.GetSiblingIndex() + 1);
// Rename clone with Numbering Scheme
clone.name = newGameObjectName;
Undo.RegisterCreatedObjectUndo(clone, "Duplicate below");
clones.Add(clone);
}
// Select new objects, if any
if (clones.Count > 0)
{
Selection.objects = clones.Cast<Object>().ToArray();
}
}
}
Thank you both of you