Skip to content

Instantly share code, notes, and snippets.

@vildninja
Created March 25, 2019 10:06
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save vildninja/fefddf7390646a113ba7ee2a5da0525e to your computer and use it in GitHub Desktop.
Save vildninja/fefddf7390646a113ba7ee2a5da0525e to your computer and use it in GitHub Desktop.
Remove missing MonoBehaviour script components in Unity 2019.1 including visiting prefafab assets.
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++;
}
}
}
@rgarlik
Copy link

rgarlik commented Jun 9, 2020

You're a legend dude

@pedro15
Copy link

pedro15 commented Nov 18, 2020

Thank you so much!!

@HappySapeta
Copy link

Thank you!

@ahmarali89
Copy link

Thank you so much

@hassan404
Copy link

Thanks a lot!

@twobitEDD
Copy link

Thank you SO MUCH! I've been slamming my head against the wall trying to fix this issue! 🙏

@tracer8
Copy link

tracer8 commented May 9, 2022

Legend! Thank you!

@varun312
Copy link

Thanks man I had like 300 missing scripts was about to think I'll have to do them by hand

@Gaebabi
Copy link

Gaebabi commented Dec 30, 2022

Thanks a lot! for 1500 missing scripts...

@engralihaiderkhan
Copy link

Thanks Bro it helped

@SamuelTechnologyProjects

Thanks a lot i was about to spend 10days fixing this

@ricojuanmanuel
Copy link

Great, thanks you very much.

@longshilin
Copy link

thks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment