コガネブログ

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

【Unity】2018.3 で Missing References が検出できなくなった時の対処方法

はじめに

using System.Linq;
using UnityEditor;
using UnityEngine;

public static class Example
{
    [MenuItem( "Tools/Hoge" )]
    private static void Hoge()
    {
        var go = Selection.activeGameObject;

        var components = go
            .GetComponents<Component>()
            .Where( c => c != null )
        ;

        foreach ( var c in components )
        {
            var so = new SerializedObject( c );
            var sp = so.GetIterator();

            while ( sp.NextVisible( true ) )
            {
                if ( sp.propertyType != SerializedPropertyType.ObjectReference ) continue;
                if ( sp.objectReferenceValue != null ) continue;
                if ( sp.objectReferenceInstanceIDValue == 0 ) continue;

                Debug.Log( "Missing!" );
            }
        }
    }
}

以前の Unity のバージョンであれば、上記のようなエディタ拡張を作成することで

f:id:baba_s:20190320141549p:plain

Inspector で参照が Missing になっているかどうかを確認することができたのですが、
Unity 2018.3 で同様の処理を実行したところ、
Missing の判定が検出できなくなっていました

(Missing でも None でも sp.objectReferenceInstanceIDValue が 0 になってしまう)

対処方法

sprite: {fileID: 0}

参照が None になっている時は fileID が 0 になり、

sprite: {fileID: 21300000, guid: 6bce31ca45f21bd40a5a6756299d5bfb, type: 3}

参照が Missing になっている時は fileID が設定されている状態になるので

  • sp.propertyType が SerializedPropertyType.ObjectReference
  • sp.objectReferenceValue が null
  • fileID が 0 ではない

上記のような判定を使用することで Unity 2018.3 でも Missing References を検出できます
以下にサンプルコードを記載します

using System.Linq;
using UnityEditor;
using UnityEngine;

public class EditTest : MonoBehaviour
{
    [MenuItem( "Tools/Hoge" )]
    private static void Hoge()
    {
        var go = Selection.activeGameObject;

        var components = go
            .GetComponents<Component>()
            .Where( c => c != null )
        ;

        foreach ( var c in components )
        {
            var so = new SerializedObject( c );
            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;

                Debug.Log( "Missing!" );
            }
        }
    }
}

参考サイト様