Unity - 查找当前场景中的Missing组件
最近遇到一个问题是从别的工程中拷贝的一个Prefab文件在保存的时候报NullRefrence的引用错误,经查找后确定是Prefab中存在丢失的脚本或者组件中丢失引用或者存在None的引用,如下几种:



手动找总会漏掉,然后还是报错,所以想到用脚本工具来查找,核心部分是判断脚本的引用存在但是引用值丢失了,如下:
if(sp.propertyType == SerializedPropertyType.ObjectReference)
{
if(sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0)
{
ShowError(context, go, c.GetType().Name, ObjectNames.NicifyVariableName(sp.name));
}
}
参考:https://www.gamasutra.com/blogs/LiorTal/20141208/231690/Finding_Missing_Object_References_in_Unity.php
完整代码:
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
public class FindMissingRefrence : MonoBehaviour
{
[MenuItem("Tools/Find Missing Refrence In Current Scene")]
public static void FindMissingRefrencesInCurrentScene()
{
var objects = GetSceneObjects();
FindMissingReferences(SceneManager.GetActiveScene().name, objects);
}
private static GameObject[] GetSceneObjects() => Resources.FindObjectsOfTypeAll().Where(go => string.IsNullOrEmpty(AssetDatabase.GetAssetPath(go)) && go.hideFlags == HideFlags.None).ToArray();
private static void FindMissingReferences(string context, GameObject[] objects)
{
foreach(var go in objects)
{
var components = go.GetComponents();
foreach(var c in components)
{
if(!c)
{
Debug.LogError("Missing Component in GO: " + FullPath(go), go);
continue;
}
SerializedObject 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(context, go, c.GetType().Name, ObjectNames.NicifyVariableName(sp.name));
}
}
}
}
}
}
private static void ShowError(string context, GameObject go, string c, string property) => Debug.LogError($"Missing Refrence in : [{context}]{FullPath(go)}. Component: {c}, Property: {property}");
private static string FullPath(GameObject go) => go.transform.parent == null ? go.name : FullPath(go.transform.parent.gameObject) + "/" + go.name;
}