using System.Text; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; /// /// Removes orphaned MonoBehaviour components whose script asset no longer exists /// (the "The referenced script on this Behaviour is missing!" warnings seen in the /// WebGPU build console). Operates on every GameObject in the currently open scene(s), /// including inactive ones. Safe: only removes components Unity already reports as missing. /// public static class RemoveMissingScripts { [MenuItem("Tools/Cleanup/Remove Missing Scripts In Open Scene(s)")] public static void RemoveInOpenScenes() { int totalRemoved = 0; int objectsAffected = 0; var report = new StringBuilder(); for (int s = 0; s < SceneManager.sceneCount; s++) { Scene scene = SceneManager.GetSceneAt(s); if (!scene.isLoaded) continue; foreach (GameObject root in scene.GetRootGameObjects()) { foreach (Transform t in root.GetComponentsInChildren(true)) { GameObject go = t.gameObject; int count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(go); if (count == 0) continue; Undo.RegisterCompleteObjectUndo(go, "Remove Missing Scripts"); int removed = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go); if (removed > 0) { totalRemoved += removed; objectsAffected++; report.AppendLine($" {removed} on '{GetPath(go)}'"); EditorSceneManager.MarkSceneDirty(scene); } } } } if (totalRemoved == 0) Debug.Log("[RemoveMissingScripts] No missing scripts found in the open scene(s)."); else Debug.Log($"[RemoveMissingScripts] Removed {totalRemoved} missing script component(s) from {objectsAffected} object(s):\n{report}\nSave the scene (Ctrl+S) to persist."); } private static string GetPath(GameObject go) { string path = go.name; Transform p = go.transform.parent; while (p != null) { path = p.name + "/" + path; p = p.parent; } return path; } }