コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】SpriteRenderer の Sprite が Missing なプレハブをすべて見つけるエディタ拡張

ソースコード

using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

internal sealed class MissingSpriteFinder : EditorWindow
{
    [MenuItem( "Window/Missing Sprite Finder" )]
    private static void Open()
    {
        GetWindow<MissingSpriteFinder>();
    }

    private void OnGUI()
    {
        if ( GUILayout.Button( "Find Missing Sprites" ) )
        {
            Find();
        }
    }

    private static void Find()
    {
        var guids         = AssetDatabase.FindAssets( "t:Prefab" );
        var stringBuilder = new StringBuilder();

        foreach ( var guid in guids )
        {
            var path   = AssetDatabase.GUIDToAssetPath( guid );
            var prefab = AssetDatabase.LoadAssetAtPath<GameObject>( path );

            if ( prefab == null ) continue;

            var spriteRenderers = prefab.GetComponentsInChildren<SpriteRenderer>( true );

            foreach ( var spriteRenderer in spriteRenderers )
            {
                // if (spriteRenderer.sprite == null)
                if ( MissingReferenceUtils.HasMissingReference( spriteRenderer ) )
                {
                    stringBuilder.AppendLine( path );
                    break;
                }
            }
        }

        var result = stringBuilder.ToString();
        EditorGUIUtility.systemCopyBuffer = result;
        Debug.Log( result );
    }
}

internal static class MissingReferenceUtils
{
    public static bool HasMissingReference( GameObject gameObject )
    {
        return gameObject
                .GetComponents<Component>()
                .Where( x => x != null )
                .Any( x => HasMissingReference( x ) )
            ;
    }

    public static bool HasMissingReference( Component component )
    {
        var so = new SerializedObject( component );
        var sp = so.GetIterator();

        while ( sp.NextVisible( true ) )
        {
            if ( sp.propertyType != SerializedPropertyType.ObjectReference ) continue;
            if ( sp.objectReferenceValue != null ) continue;
            if ( !sp.hasChildren ) continue;
            var fileId = sp.FindPropertyRelative( "m_FileID" );
            if ( fileId == null ) continue;
            if ( fileId.intValue == 0 ) continue;

            return true;
        }

        return false;
    }
}