Skip to content

Instantly share code, notes, and snippets.

@ProGM
Last active July 18, 2023 14:22
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProGM/a40acd8ebbb91eb7b2295e65d5eb42c8 to your computer and use it in GitHub Desktop.
Save ProGM/a40acd8ebbb91eb7b2295e65d5eb42c8 to your computer and use it in GitHub Desktop.
Finding Missing References in Unity 5.4+
// Based on http://www.tallior.com/find-missing-references-unity/
// It fixes deprecations and checks for missing references every time a new scene is loaded
// Moreover, it inspects missing references in animators and animation frames
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Linq;
[InitializeOnLoad]
public static class LatestScenes
{
static string currentScene;
static LatestScenes()
{
EditorApplication.hierarchyWindowChanged += hierarchyWindowChanged;
}
static void hierarchyWindowChanged()
{
if (currentScene != EditorSceneManager.GetActiveScene().name)
{
CheckMissingReferences.FindMissingReferencesInCurrentScene ();
currentScene = EditorSceneManager.GetActiveScene().name;
}
}
}
public static class CheckMissingReferences {
[MenuItem("Tools/Show Missing Object References in all scenes", false, 51)]
public static void MissingSpritesInAllScenes()
{
foreach (var scene in EditorBuildSettings.scenes.Where(s => s.enabled))
{
EditorSceneManager.OpenScene(scene.path);
var objects = Object.FindObjectsOfType<GameObject> ();
FindMissingReferences(scene.path, objects);
}
}
[MenuItem("Tools/Show Missing Object References in scene", false, 50)]
public static void FindMissingReferencesInCurrentScene()
{
var objects = Object.FindObjectsOfType<GameObject> ();
FindMissingReferences(EditorSceneManager.GetActiveScene().name, objects);
}
[MenuItem("Tools/Show Missing Object References in assets", false, 52)]
public static void MissingSpritesInAssets()
{
var allAssets = AssetDatabase.GetAllAssetPaths();
var objs = allAssets.Select(a => AssetDatabase.LoadAssetAtPath(a, typeof(GameObject)) as GameObject).Where(a => a != null).ToArray();
FindMissingReferences("Project", objs);
}
public static void FindMissingReferences(string sceneName, GameObject[] objects)
{
foreach (var go in objects)
{
var components = go.GetComponents<Component> ();
foreach (var c in components)
{
var so = new SerializedObject(c);
var sp = so.GetIterator();
while (sp.NextVisible(true))
{
if (sp.propertyType == SerializedPropertyType.ObjectReference)
{
if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0)
{
ShowError(FullObjectPath(go), sp.name, sceneName);
}
}
}
var animator = c as Animator;
if (animator != null) {
CheckAnimatorReferences (animator);
}
}
}
}
public static void CheckAnimatorReferences(Animator component)
{
if (component.runtimeAnimatorController == null) {
return;
}
foreach (AnimationClip ac in component.runtimeAnimatorController.animationClips) {
var so = new SerializedObject (ac);
var sp = so.GetIterator ();
while (sp.NextVisible (true)) {
if (sp.propertyType == SerializedPropertyType.ObjectReference) {
if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0) {
Debug.LogError ("Missing reference found in: " + FullObjectPath (component.gameObject) + "Animation: " + ac.name + ", Property : " + sp.name + ", Scene: " + EditorSceneManager.GetActiveScene ().name);
}
}
}
}
}
static void ShowError (string objectName, string propertyName, string sceneName)
{
Debug.LogError("Missing reference found in: " + objectName + ", Property : " + propertyName + ", Scene: " + sceneName);
}
static string FullObjectPath(GameObject go)
{
return go.transform.parent == null ? go.name : FullObjectPath(go.transform.parent.gameObject) + "/" + go.name;
}
}
@marcosoldati
Copy link

I'm using your script in a couple of my projects. Today I stumbled over some functionality to slightly improve it. Debug.Log takes a second parameter context. This allows the Unity Editor to highlight the context object in the scene tree when you click on the message. Works at least as long as it's in the current scene. Super useful.

Required changes:

Line 98: add ac as second parameter

Line 74: add c a fourth param and adjust ShowError as below.

static void ShowError(string objectName, string propertyName, string sceneName, Object context)
	{
		Debug.LogError("Missing reference found in: " + objectName + ", Property : " + propertyName + ", Scene: " + sceneName, context);
	}

Hope that helps. Marco

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