Unity 查找各种丢失的引用

最近有一个小的需求,需要在prefab保存的时候检查某个组件有没有引用丢失,去看了网上一些检查方式,都没有达到目的;

在这篇文章里找到一个可用的方式,http://www.li0rtal.com/find-missing-references-unity/

然后根据自己的需要做了一些调整,大概代码如下

using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;
using System.Reflection;


public class ArtPrefabAutoConfigurer : AssetPostprocessor 
{
    private static string[] missTagValueArray = {
        "None (Game Object)",
        "None (UI Widget)",
        "None (Transform)",
        "None (UILabel)",
        "None (UI Event Listener)",
        "None (Component)"
    };
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        List prefabPathList = new List();
        foreach (string str in importedAssets)
        {
            Regex prefabSuffix = new Regex(".prefab$");
            if (prefabSuffix.IsMatch(str)){
                prefabPathList.Add(str);
                CheckPrefab(str);
                break;
            }
        }

        if (prefabPathList.Count == 0)
            return;

        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
}

private static void CheckPrefab(string prefabPath){
    var rootGo = AssetDatabase.LoadAssetAtPath(prefabPath);
    var newPrefab = PrefabUtility.InstantiatePrefab(rootGo) as GameObject;
    var ret = CheckMissing(newPrefab);
    if(ret){
        EditorUtility.DisplayDialog("警告", "!!!有引用丢失,请确保修复后上传!!!\n打开日志窗口(ctrl+shift+c)查看丢失", "确定");
    }
    GameObject.DestroyImmediate(newPrefab);
}

private static bool CheckMissing(Object item){
    var flag = false;
    GameObject go = item as GameObject;
    if (go == null)
        return flag;
    Component[] cps = go.GetComponentsInChildren();
    for (int idx = 0; idx < cps.Length; idx++)
    {
        Component cp = cps[idx];
        if(cp.GetType().Name != "UIDataBind"){
            continue;
        }
        SerializedObject so = new SerializedObject(cp);
        var sp = so.GetIterator();

        var objRefValueMethod = typeof(SerializedProperty).GetProperty("objectReferenceStringValue",
            BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        while (sp.Next(true))
        {
            if (sp.propertyType == SerializedPropertyType.ObjectReference)
            {
                string objectReferenceStringValue = string.Empty;
                
                if (objRefValueMethod != null)
                {
                    objectReferenceStringValue = (string) objRefValueMethod.GetGetMethod(true).Invoke(sp, new object[] { });
                }

                if (sp.objectReferenceValue == null
                    && (sp.objectReferenceInstanceIDValue != 0 || objectReferenceStringValue.StartsWith("Missing") || CheckMissingTagValue(objectReferenceStringValue)))
                {
                    flag = true;
					ShowError(go, cp.GetType().Name, ObjectNames.NicifyVariableName(sp.name));
                }
            }
        }
    }
    return flag;
}

private static bool CheckMissingTagValue(string value){
    for(int i = 0; i < missTagValueArray.Length; i++){
        if(missTagValueArray[i] == value){
            return true;
        }
    }
    return false;
}

private static void ShowError(GameObject go, string componentName, string propertyName)
{
    var ERROR_TEMPLATE = "Missing Reference in GameObject: {0}. Component: {1}, Property: {2}";
    Debug.LogError(string.Format(ERROR_TEMPLATE, GetFullPath(go), componentName, propertyName), go);
}

private static string GetFullPath(GameObject go)
{
    return go.transform.parent == null
        ? go.name
            : GetFullPath(go.transform.parent.gameObject) + "/" + go.name;
}

}

 

你可能感兴趣的:(Unity,Editor,unity游戏开发)