DeleteDuplicatedObjectsEditorWindow.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEditor;
  4. using UnityEngine;
  5. public class DeleteDuplicatedObjectsEditorWindow : EditorWindow
  6. {
  7. private int deleted;
  8. private int skipped;
  9. private int overallObjects;
  10. [MenuItem("Window/Delete Duplicates")]
  11. private static void ShowWindow()
  12. {
  13. var window = GetWindow<DeleteDuplicatedObjectsEditorWindow>();
  14. window.titleContent = new GUIContent("Delete Duplicates");
  15. window.Show();
  16. }
  17. private void OnGUI()
  18. {
  19. if (GUILayout.Button("Delete Duplicates"))
  20. {
  21. OnDeleteDuplicates();
  22. }
  23. if (GUILayout.Button("Delete Everything"))
  24. {
  25. OnDeleteEverything();
  26. }
  27. GUILayout.Label($"Total number objects {overallObjects}");
  28. GUILayout.Label($"Deleted items: {deleted}");
  29. GUILayout.Label($"Skipped items: {skipped}");
  30. //TODO: maybe show ref to skipped items
  31. }
  32. private void OnDeleteEverything()
  33. {
  34. var objects = FindObjectsOfType<MeshRenderer>();
  35. foreach (var meshRenderer in objects)
  36. {
  37. if (meshRenderer == null) continue;
  38. var prefab = PrefabUtility.GetOutermostPrefabInstanceRoot(meshRenderer.gameObject);
  39. DestroyImmediate(prefab != null ? prefab : meshRenderer.gameObject);
  40. }
  41. }
  42. private void OnDeleteDuplicates()
  43. {
  44. skipped = 0;
  45. deleted = 0;
  46. List<GameObject> toDelete = new List<GameObject>();
  47. var objects = FindObjectsOfType<MeshRenderer>();
  48. var objectsAtPos = new Dictionary<Vector3, List<GameObject>>();
  49. overallObjects = objects.Length;
  50. Debug.Log($"Found {overallObjects} GameObjects");
  51. foreach (var o in objects)
  52. {
  53. var pos = o.transform.position;
  54. if (!objectsAtPos.ContainsKey(pos))
  55. {
  56. var l = new List<GameObject> {o.gameObject};
  57. objectsAtPos[pos] = l;
  58. }
  59. else
  60. {
  61. objectsAtPos[pos].Add(o.gameObject);
  62. }
  63. }
  64. Debug.Log($"Done sorting");
  65. var objs = objectsAtPos.Values.Where(l => l.Count > 1);
  66. var enumerable = objs as List<GameObject>[] ?? objs.ToArray();
  67. Debug.LogWarning($"{enumerable.Count()} gameobjects at exact same position");
  68. Debug.Log("Deleting objects..");
  69. foreach (var o in enumerable)
  70. {
  71. var rMap = new Dictionary<Quaternion, List<GameObject>>();
  72. foreach (var d in o)
  73. {
  74. if (d == null) continue;
  75. var rot = d.transform.rotation;
  76. if (rMap.ContainsKey(rot))
  77. {
  78. rMap[rot].Add(d);
  79. }
  80. else
  81. {
  82. rMap[rot] = new List<GameObject> {d};
  83. }
  84. //Destroy(d);
  85. }
  86. var samePosAndRot = rMap.Values.Max(v => v.Count);
  87. Debug.Log($"max same pos and rot = {samePosAndRot}");
  88. if (samePosAndRot < 2) continue;
  89. var resultsWithMax = rMap.Values.Where(l => l.Count == samePosAndRot);
  90. foreach (var r in resultsWithMax)
  91. {
  92. Debug.Log($"Names: {string.Join(",", r.Select(x => x.name))}");
  93. if (r.Aggregate((result, item) =>
  94. {
  95. if (result == null) return null;
  96. else
  97. {
  98. var rIndex = result.name.IndexOf('(');
  99. var iIndex = item.name.IndexOf('(');
  100. var rBase = rIndex > 0 ? result.name.Substring(0, rIndex) : result.name;
  101. var iBase = iIndex > 0 ? item.name.Substring(0, iIndex) : item.name;
  102. return rBase.Equals(iBase) ? item : null;
  103. }
  104. }) != null)
  105. {
  106. for (var index = 1; index < r.Count; index++)
  107. {
  108. var gameObject1 = r[index];
  109. if (gameObject1.transform.childCount == 0)
  110. {
  111. var prefabParent = PrefabUtility.GetOutermostPrefabInstanceRoot(gameObject1);
  112. if (prefabParent != null)
  113. {
  114. Debug.LogWarning($"Destroyed prefab {prefabParent.name}!");
  115. //DestroyImmediate(prefabParent);
  116. toDelete.Add(prefabParent);
  117. }
  118. else
  119. {
  120. toDelete.Add(gameObject1);
  121. //DestroyImmediate(gameObject1);
  122. }
  123. }
  124. else
  125. {
  126. Debug.LogError($"Did not destroy {gameObject1.name}");
  127. skipped++;
  128. }
  129. deleted++;
  130. }
  131. }
  132. }
  133. }
  134. foreach (var d in toDelete)
  135. {
  136. if (d != null)
  137. {
  138. DestroyImmediate(d);
  139. }
  140. }
  141. Debug.LogWarning($"Deleted {deleted} items!");
  142. Debug.LogWarning($"Skipped {skipped} items!");
  143. }
  144. }