DeleteDuplicatedObjectsEditorWindow.cs 5.5 KB

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