Skip to content

Instantly share code, notes, and snippets.

@vildninja
Created March 25, 2019 10:06
Show Gist options
  • Select an option

  • Save vildninja/fefddf7390646a113ba7ee2a5da0525e to your computer and use it in GitHub Desktop.

Select an option

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++;
}
}
}
@pedro15
Copy link
Copy Markdown

pedro15 commented Nov 18, 2020

Thank you so much!!

@HappySapeta
Copy link
Copy Markdown

Thank you!

@ahmarali89
Copy link
Copy Markdown

Thank you so much

@hassan404
Copy link
Copy Markdown

Thanks a lot!

@twobitEDD
Copy link
Copy Markdown

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

@tracer8
Copy link
Copy Markdown

tracer8 commented May 9, 2022

Legend! Thank you!

@varun312
Copy link
Copy Markdown

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

@Gaebabi
Copy link
Copy Markdown

Gaebabi commented Dec 30, 2022

Thanks a lot! for 1500 missing scripts...

@engralihaiderkhan
Copy link
Copy Markdown

Thanks Bro it helped

@SamuelTechnologyProjects
Copy link
Copy Markdown

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

@ricojuanmanuel
Copy link
Copy Markdown

Great, thanks you very much.

@longshilin
Copy link
Copy Markdown

thks

@ARosyidG
Copy link
Copy Markdown

ARosyidG commented Jun 4, 2024

Thanks you

@theyonatan
Copy link
Copy Markdown

Wow, just like magic. Thank you! This should be built in!

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