Updating because GetPrefabParent has been deprecated around 2019.1 (plus some extra functionality)
This works on the scene view only - if you want to duplicate in the project (ie. assets) see Ben Blaut’s comment
// Map it to Alt + D
[UnityEditor.MenuItem("GaneObject/Duplicate &D", false, 0)]
public static void Duplicate()
{
List<UnityEngine.Object> clones = new List<UnityEngine.Object>();
foreach (GameObject o in Selection.gameObjects)
{
if (!o.transform) continue; // Scene view
GameObject clone;
GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(o);
if (prefab != null)
clone = PrefabUtility.InstantiatePrefab(prefab, o.transform.parent) as GameObject;
else
clone = UnityEngine.Object.Instantiate(o, o.transform.parent);
if (clone == null) continue;
// Do any operations you want on to the cloned object (otherwise this function behaves just like Ctrl+D
// <---- CUSTOM LOGIC BEGIN ---->
// ie. If you want to randomize scale / rotation you can do so here
// clone.transform.localScale = ;
// clone.transform.rotation = ;
// <---- CUSTOM LOGIC END ---->
clones.Add(clone);
// Register the duplicated objects to be able to undo
Undo.RegisterCreatedObjectUndo(clone, "Duplicate");
}
if (clones.Count == 0) return;
// Select the duplicated objects
Selection.objects = clones.ToArray();
}