using System.Collections.Generic; using UnityEngine; using UnityEditor; using System; public class RemoveMissingScripts : EditorWindow { private static void RemoveMissingScriptsFromSelectedObjects() { List gameObjectsWithMissingScripts = new List(); foreach (GameObject go in Selection.gameObjects) { Component[] components = go.GetComponents(); foreach (Component component in components) { if (component == null) { gameObjectsWithMissingScripts.Add(go); break; } } } foreach (GameObject go in gameObjectsWithMissingScripts) { Component[] components = go.GetComponents(); for (int i = 0; i < components.Length; i++) { if (components[i] == null) { DestroyImmediate(go.GetComponent(components[i].GetType())); i--; // Component array has changed, so decrement index to check new component at same position } } } EditorUtility.DisplayDialog("Completed", "Removed missing scripts from selected objects.", "OK"); } [MenuItem("Tools/Remove Missing Scripts from Scene")] private static void RemoveMissingScriptsInScene() { GameObject[] allObjects = FindObjectsByType(FindObjectsSortMode.None); int totalRemovedScripts = 0; foreach (GameObject obj in allObjects) { int removedCount = RemovesMissingScripts(obj); if (removedCount > 0) { totalRemovedScripts += removedCount; Debug.Log($"Removed {removedCount} missing scripts from GameObject: {obj.name}"); } } Debug.Log($"Total removed missing scripts from scene: {totalRemovedScripts}"); } private static int RemovesMissingScripts(GameObject obj) { int removedCount = 0; Transform[] transforms = obj.GetComponentsInChildren(true); foreach (Transform t in transforms) { Component[] components = t.gameObject.GetComponents(); SerializedObject so = new SerializedObject(t.gameObject); SerializedProperty prop = so.FindProperty("m_Component"); int nullCount = 0; for (int i = 0; i < components.Length; i++) { if (components[i] == null) { prop.DeleteArrayElementAtIndex(i - nullCount); nullCount++; removedCount++; } } so.ApplyModifiedProperties(); } return removedCount; } [MenuItem("Tools/Remove Missing Scripts from Selected Prefabs")] private static void RemoveMissingScriptsInSelectedPrefabs() { // 获取选中的所有对象 GameObject[] selectedObjects = Selection.gameObjects; int totalRemovedScripts = 0; foreach (GameObject selectedObject in selectedObjects) { string prefabPath = AssetDatabase.GetAssetPath(selectedObject); if (string.IsNullOrEmpty(prefabPath) || PrefabUtility.GetPrefabAssetType(selectedObject) == PrefabAssetType.NotAPrefab) { Debug.LogWarning($"Selected object '{selectedObject.name}' is not a prefab."); continue; } // 打开预设以编辑模式加载 GameObject prefabInstance = PrefabUtility.LoadPrefabContents(prefabPath); int removedCount = RemoveAllMissingScripts(prefabInstance); if (removedCount > 0) { totalRemovedScripts += removedCount; Debug.Log($"Removed {removedCount} missing scripts from prefab: {prefabPath}"); PrefabUtility.SaveAsPrefabAsset(prefabInstance, prefabPath); } // 释放实例 PrefabUtility.UnloadPrefabContents(prefabInstance); } Debug.Log($"Total removed missing scripts from selected prefabs: {totalRemovedScripts}"); } private static int RemoveAllMissingScripts(GameObject obj) { int removedCount = 0; Transform[] transforms = obj.GetComponentsInChildren(true); foreach (Transform t in transforms) { Component[] components = t.gameObject.GetComponents(); SerializedObject so = new SerializedObject(t.gameObject); SerializedProperty prop = so.FindProperty("m_Component"); int nullCount = 0; for (int i = 0; i < components.Length; i++) { if (components[i] == null) { prop.DeleteArrayElementAtIndex(i - nullCount); nullCount++; removedCount++; } } so.ApplyModifiedProperties(); } return removedCount; } }