Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ilhamachmada/753c129ef8e7403eb5097c8bc5dbd351 to your computer and use it in GitHub Desktop.
Save ilhamachmada/753c129ef8e7403eb5097c8bc5dbd351 to your computer and use it in GitHub Desktop.

Revisions

  1. @vildninja vildninja created this gist Mar 25, 2019.
    63 changes: 63 additions & 0 deletions RemoveMissingScriptsRecursively.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEditor;
    public static class FindMissingScriptsRecursively
    {
    [MenuItem("Auto/Remove Missing Scripts Recursively Visit Prefabs")]
    private static void FindAndRemoveMissingInSelected()
    {
    // EditorUtility.CollectDeepHierarchy does not include inactive children
    var deeperSelection = Selection.gameObjects.SelectMany(go => go.GetComponentsInChildren<Transform>(true))
    .Select(t => t.gameObject);
    var prefabs = new HashSet<Object>();
    int compCount = 0;
    int goCount = 0;
    foreach (var go in deeperSelection)
    {
    int count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(go);
    if (count > 0)
    {
    if (PrefabUtility.IsPartOfAnyPrefab(go))
    {
    RecursivePrefabSource(go, prefabs, ref compCount, ref goCount);
    count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(go);
    // if count == 0 the missing scripts has been removed from prefabs
    if (count == 0)
    continue;
    // if not the missing scripts must be prefab overrides on this instance
    }

    Undo.RegisterCompleteObjectUndo(go, "Remove missing scripts");
    GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go);
    compCount += count;
    goCount++;
    }
    }

    Debug.Log($"Found and removed {compCount} missing scripts from {goCount} GameObjects");
    }

    // Prefabs can both be nested or variants, so best way to clean all is to go through them all
    // rather than jumping straight to the original prefab source.
    private static void RecursivePrefabSource(GameObject instance, HashSet<Object> prefabs, ref int compCount,
    ref int goCount)
    {
    var source = PrefabUtility.GetCorrespondingObjectFromSource(instance);
    // Only visit if source is valid, and hasn't been visited before
    if (source == null || !prefabs.Add(source))
    return;

    // go deep before removing, to differantiate local overrides from missing in source
    RecursivePrefabSource(source, prefabs, ref compCount, ref goCount);

    int count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(source);
    if (count > 0)
    {
    Undo.RegisterCompleteObjectUndo(source, "Remove missing scripts");
    GameObjectUtility.RemoveMonoBehavioursWithMissingScript(source);
    compCount += count;
    goCount++;
    }
    }
    }