unity 程式碼批量修改Remove Missing Script和批量修改指定元件的內容

以夢為馬,不負韶華發表於2018-10-16

昨天在專案開發中,發現一個問題,就是一些指令碼已經被廢棄,但是這些廢棄指令碼還是被繫結在某些預製體中,這時候執行就會產生很多Missing Script的警告資訊,這些警告雖不影響程式碼的實際執行,但是一個大專案肯定不能出現的N多的警告資訊,並且這裡通過手動去找肯定不現實,所以這裡我們就同一個指令碼去實現自動去遍歷所有的prefab然後移除Missing的元件,下面是具體的程式碼資訊。

1.首先在工程中建立一個Editro資料夾,將指令碼放在Editor資料夾下

2.通過選中檔案,通過編輯器實現遍歷該資料夾下的所有prefab:

    [MenuItem("工具/物件移除丟失指令碼")]
    static void GetAllGo()
    {
        //尋找你選中資料夾下的所有檔案
        object[] obj = Selection.GetFiltered(typeof(object), SelectionMode.DeepAssets);
        for (int i = 0; i < obj.Length; i++)
        {
            //獲取檔案的字尾資訊
            string ext = System.IO.Path.GetExtension(obj[i].ToString());
            //這裡篩選出不是預製體的物體
            if (!ext.Contains(".GameObject"))
            {
                continue;
            }

            GameObject go = (GameObject)obj[i];

            // 移除子物體下的指令碼丟失
            foreach (Transform trans in go.GetComponentsInChildren<Transform>(true))
            {
                CleanMissingScript(trans.gameObject, go);
            }
        }
    }

3.找到prefab,去遍歷她的所有子物體,並實現直接移除相應的空元件:

    static void CleanMissingScript(GameObject go, GameObject parentGO)
    {
        var components = go.GetComponents<Component>();
        var serializedObject = new SerializedObject(go);
        var prop = serializedObject.FindProperty("m_Component");
        int r = 0;
        for (int j = 0; j < components.Length; j++)
        {
            if (components[j] == null)
            {
                prop.DeleteArrayElementAtIndex(j - r);
                MyDebug.Log("成功移除丟失指令碼,gameObject name: " + go.name + " ---父類prefab name:" + parentGO.name);
                r++;
            }
        }
        serializedObject.ApplyModifiedProperties();
    }

4.如果還要做其他操作,比如我們寫了一個擴充套件的button指令碼,這時候我們不可能通過手動去把所有之前的button換成新的butonPlus,所以這時候就需要去程式碼自動實現:

    static void CleanMissingScript(GameObject go, GameObject parentGO)
    {
        var components = go.GetComponents<Component>();

        //如果當前元件有按鈕
        if (go.GetComponent<UnityEngine.UI.Button>() != null)
        {
            Button btn = go.GetAddComponent<Button>();
            //copy之前的元件資訊
            UnityEditorInternal.ComponentUtility.CopyComponent(btn);
            //移除元件資訊
            GameObject.DestroyImmediate(btn);
            //TODO:新增新的元件資訊

        }       
        serializedObject.ApplyModifiedProperties();
    }

5.下面是完整指令碼:

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;

/// <summary>
/// 移除專案中go上丟失的指令碼
/// </summary>
public class RemoveMissingScript
{
    [MenuItem("SlgTool/程式工具/物件移除丟失指令碼")]
    static void GetAllGo()
    {
        object[] obj = Selection.GetFiltered(typeof(object), SelectionMode.DeepAssets);
        for (int i = 0; i < obj.Length; i++)
        {
            string ext = System.IO.Path.GetExtension(obj[i].ToString());
            Debug.Log("name:" + ext);
            if (!ext.Contains(".GameObject"))
            {
                continue;
            }

            GameObject go = (GameObject)obj[i];

            // 移除子物體下的指令碼丟失
            foreach (Transform trans in go.GetComponentsInChildren<Transform>(true))
            {
                CleanMissingScript(trans.gameObject, go);
            }
        }

    }

    static void CleanMissingScript(GameObject go, GameObject parentGO)
    {
        var components = go.GetComponents<Component>();   
        var serializedObject = new SerializedObject(go);
        var prop = serializedObject.FindProperty("m_Component");
        int r = 0;
        for (int j = 0; j < components.Length; j++)
        {
            if (components[j] == null)
            {
                prop.DeleteArrayElementAtIndex(j - r);
                MyDebug.Log("成功移除丟失指令碼,gameObject name: " + go.name + " ---父類prefab name:" + parentGO.name);
                r++;
            }
        }
        serializedObject.ApplyModifiedProperties();
    }

}

這裡就是一個完整的程式碼自動查詢prefab下的空元件,然後移除的程式碼。

想了解更多請新增下方公眾號,或者新增QQ群:879354767

相關文章