Files

234 lines
7.1 KiB
C#

using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace BrewMonster.Scripts.Utils.Editor
{
public static class ClearMissingScript
{
[MenuItem("Tools/Brew Monster/Clear Missing Script/Active Scene")]
public static void ClearMissingScriptsInActiveScene()
{
var scene = SceneManager.GetActiveScene();
if (!scene.IsValid())
{
EditorUtility.DisplayDialog("Clear Missing Script", "No valid active scene.", "OK");
return;
}
int removedCount = 0;
var roots = scene.GetRootGameObjects();
foreach (var root in roots)
{
Undo.RegisterFullObjectHierarchyUndo(root, "Clear Missing Scripts");
removedCount += RemoveMissingScriptsRecursive(root);
}
if (removedCount > 0)
{
EditorSceneManager.MarkSceneDirty(scene);
}
EditorUtility.DisplayDialog("Clear Missing Script", $"Removed {removedCount} missing script(s) from active scene.", "OK");
}
[MenuItem("Tools/Brew Monster/Clear Missing Script/Prefabs in Selected Folder", true)]
public static bool ValidateClearMissingScriptsInSelectedFolder()
{
Object selectedObject = Selection.activeObject;
if (selectedObject == null)
return false;
string folderPath = AssetDatabase.GetAssetPath(selectedObject);
return AssetDatabase.IsValidFolder(folderPath);
}
[MenuItem("Tools/Brew Monster/Clear Missing Script/Prefabs in Selected Folder")]
public static void ClearMissingScriptsInSelectedFolder()
{
Object selectedObject = Selection.activeObject;
if (selectedObject == null)
{
EditorUtility.DisplayDialog("Clear Missing Script",
"Please select a folder in the Project window first.", "OK");
return;
}
string folderPath = AssetDatabase.GetAssetPath(selectedObject);
if (!AssetDatabase.IsValidFolder(folderPath))
{
EditorUtility.DisplayDialog("Clear Missing Script",
"Selected object is not a valid folder. Please select a folder in the Project window.", "OK");
return;
}
if (!EditorUtility.DisplayDialog("Clear Missing Script in Folder",
$"This will process all prefabs in:\n{folderPath}\n\nContinue?",
"Yes", "Cancel"))
{
return;
}
ProcessPrefabsInFolder(folderPath);
}
[MenuItem("Tools/Brew Monster/Clear Missing Script/All Prefabs")]
public static void ClearMissingScriptsInPrefabs()
{
if (!EditorUtility.DisplayDialog("Clear Missing Script in Prefabs",
"This will process all prefabs in the project. This may take a while. Continue?",
"Yes", "Cancel"))
{
return;
}
ProcessPrefabsInFolder("Assets");
}
private static void ProcessPrefabsInFolder(string folderPath)
{
string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab", new[] { folderPath });
int totalPrefabs = prefabGUIDs.Length;
if (totalPrefabs == 0)
{
EditorUtility.DisplayDialog("Clear Missing Script",
$"No prefabs found in folder:\n{folderPath}", "OK");
return;
}
int processedCount = 0;
int totalRemovedCount = 0;
int prefabsWithRemovals = 0;
EditorUtility.DisplayProgressBar("Clear Missing Scripts", "Processing prefabs...", 0f);
try
{
foreach (string guid in prefabGUIDs)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
processedCount++;
EditorUtility.DisplayProgressBar("Clear Missing Scripts",
$"Processing: {assetPath} ({processedCount}/{totalPrefabs})",
(float)processedCount / totalPrefabs);
GameObject prefabRoot = PrefabUtility.LoadPrefabContents(assetPath);
if (prefabRoot != null)
{
int removedCount = RemoveMissingScriptsRecursive(prefabRoot);
if (removedCount > 0)
{
PrefabUtility.SaveAsPrefabAsset(prefabRoot, assetPath);
totalRemovedCount += removedCount;
prefabsWithRemovals++;
Debug.Log($"[ClearMissingScript] Removed {removedCount} missing script(s) from prefab: {assetPath}");
}
PrefabUtility.UnloadPrefabContents(prefabRoot);
}
}
AssetDatabase.SaveAssets();
}
finally
{
EditorUtility.ClearProgressBar();
}
EditorUtility.DisplayDialog("Clear Missing Script",
$"Processed {processedCount} prefab(s) in folder:\n{folderPath}\n\nRemoved {totalRemovedCount} missing script(s) from {prefabsWithRemovals} prefab(s).",
"OK");
}
[MenuItem("Tools/Brew Monster/Clear Missing Script/Scene and Prefabs")]
public static void ClearMissingScriptsInSceneAndPrefabs()
{
if (!EditorUtility.DisplayDialog("Clear Missing Script",
"This will process the active scene and all prefabs in the project. This may take a while. Continue?",
"Yes", "Cancel"))
{
return;
}
int sceneRemovedCount = 0;
var scene = SceneManager.GetActiveScene();
if (scene.IsValid())
{
var roots = scene.GetRootGameObjects();
foreach (var root in roots)
{
Undo.RegisterFullObjectHierarchyUndo(root, "Clear Missing Scripts");
sceneRemovedCount += RemoveMissingScriptsRecursive(root);
}
if (sceneRemovedCount > 0)
{
EditorSceneManager.MarkSceneDirty(scene);
}
}
string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab");
int totalPrefabs = prefabGUIDs.Length;
int processedCount = 0;
int prefabRemovedCount = 0;
int prefabsWithRemovals = 0;
EditorUtility.DisplayProgressBar("Clear Missing Scripts", "Processing prefabs...", 0f);
try
{
foreach (string guid in prefabGUIDs)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
processedCount++;
EditorUtility.DisplayProgressBar("Clear Missing Scripts",
$"Processing: {assetPath} ({processedCount}/{totalPrefabs})",
(float)processedCount / totalPrefabs);
GameObject prefabRoot = PrefabUtility.LoadPrefabContents(assetPath);
if (prefabRoot != null)
{
int removedCount = RemoveMissingScriptsRecursive(prefabRoot);
if (removedCount > 0)
{
PrefabUtility.SaveAsPrefabAsset(prefabRoot, assetPath);
prefabRemovedCount += removedCount;
prefabsWithRemovals++;
}
PrefabUtility.UnloadPrefabContents(prefabRoot);
}
}
AssetDatabase.SaveAssets();
}
finally
{
EditorUtility.ClearProgressBar();
}
int totalRemoved = sceneRemovedCount + prefabRemovedCount;
EditorUtility.DisplayDialog("Clear Missing Script",
$"Scene: Removed {sceneRemovedCount} missing script(s).\n" +
$"Prefabs: Processed {processedCount} prefab(s), removed {prefabRemovedCount} missing script(s) from {prefabsWithRemovals} prefab(s).\n" +
$"Total: {totalRemoved} missing script(s) removed.",
"OK");
}
private static int RemoveMissingScriptsRecursive(GameObject gameObject)
{
int removed = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(gameObject);
for (int i = 0; i < gameObject.transform.childCount; i++)
{
removed += RemoveMissingScriptsRecursive(gameObject.transform.GetChild(i).gameObject);
}
return removed;
}
}
}