You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
5.0 KiB
148 lines
5.0 KiB
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEditor; |
|
using System; |
|
|
|
public class RemoveMissingScripts : EditorWindow |
|
{ |
|
private static void RemoveMissingScriptsFromSelectedObjects() |
|
{ |
|
List<GameObject> gameObjectsWithMissingScripts = new List<GameObject>(); |
|
foreach (GameObject go in Selection.gameObjects) |
|
{ |
|
Component[] components = go.GetComponents<Component>(); |
|
foreach (Component component in components) |
|
{ |
|
if (component == null) |
|
{ |
|
gameObjectsWithMissingScripts.Add(go); |
|
break; |
|
} |
|
} |
|
} |
|
foreach (GameObject go in gameObjectsWithMissingScripts) |
|
{ |
|
Component[] components = go.GetComponents<Component>(); |
|
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<GameObject>(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<Transform>(true); |
|
|
|
foreach (Transform t in transforms) |
|
{ |
|
Component[] components = t.gameObject.GetComponents<Component>(); |
|
|
|
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<Transform>(true); |
|
|
|
foreach (Transform t in transforms) |
|
{ |
|
Component[] components = t.gameObject.GetComponents<Component>(); |
|
|
|
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; |
|
} |
|
} |