Unity 獲取UI界面結構的工具


  開發的時候必不可少的需要要獲取一個界面的子對象組件,雖然很簡單但是如果每次獲取都敲一次代碼,也是一鍵很恐怖的事情。

  現在項目用了一個工具,對着界面點一下,就會導出匹配這個界面結構的類。只要初始化這個類,就可以很方便的獲取這個界面子對象的組件。

  工具思路是這樣的:

  1、根據子對象的命名來確定需要獲取的組件。比如后綴_txt表示UILabel,_go表示GameObject。

  2、遍歷所有子對象,將帶后綴的子對象緩存起來。

  3、根據緩存的子對象,按照一定字符串拼接規則,寫到本地腳本。

  一個界面結構和導出的界面腳本結果如下

  

  只要把界面的資源(Gameobject)傳進去,就可以直接獲取子對象的組件,大大提高了開發效率。當然了,工程里對這個腳本進行了一系列封裝和抽象,這里是單獨摘出來演示的。

  (ps:這是我第一個項目,所以不清楚其他項目怎么處理這個問題的,如果有更好的思路務必告訴我)

  閑話少說,直接上干貨。(注釋寫的比較全,就不秀我那渣渣的表達能力了)

  工具腳本:

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

public class CreateSprite {
    //當前操作的對象
    private static GameObject CurGo;
    //后綴對應的組件類型
    public static Dictionary<string, string> typeMap = new Dictionary<string, string>()
    {   
        { "sp", typeof(UISprite).Name },
        { "txt", typeof(UILabel).Name },
        { "btn", typeof(UIButton).Name },
        { "go", typeof(GameObject).Name},
    };
    //腳本模版
    private static CreateSpriteUnit info;

    //在Project窗口下,選中要導出的界面,然后點擊GameObject/導出腳本
    [MenuItem("GameObject/導出腳本")]
    public static void CreateSpriteAction()
    {
        GameObject[] gameObjects = Selection.gameObjects;
        //保證只有一個對象
        if (gameObjects.Length==1)
        {
            info = new CreateSpriteUnit();
            CurGo = gameObjects[0];
            ReadChild(CurGo.transform);
            info.classname = CurGo.name + "UIPanel";
            info.WtiteClass();
            info = null;
            CurGo = null;
        }
        else
        {
            EditorUtility.DisplayDialog("警告", "你只能選擇一個GameObject", "確定");
        }
    }
    //遍歷所有子對象,GetChild方法只能獲取第一層子對象。
    public static void ReadChild(Transform tf)
    {
        foreach (Transform child in tf)
        {
            string[] typeArr = child.name.Split('_');
            if (typeArr.Length > 1)
            {
                string typeKey = typeArr[typeArr.Length - 1];
                if (typeMap.ContainsKey(typeKey))
                {
                    info.evenlist.Add(new UIInfo(child.name, typeKey, buildGameObjectPath(child).Replace(CurGo.name + "/","")));
                }

            }
            if (child.childCount > 0)
            {
                ReadChild(child);
            }
        }
    }
    //獲取路徑,這個路徑是帶當前對象名的,需要用Replace替換掉頭部
    private static string buildGameObjectPath(Transform obj)
    {
        var buffer = new StringBuilder();

        while (obj != null)
        {
            if (buffer.Length > 0)
                buffer.Insert(0, "/");
            buffer.Insert(0, obj.name);
            obj = obj.parent;
        }
        return buffer.ToString();
    }
}
//導出腳本的模版
public class CreateSpriteUnit
{
    public string classname;
    public string template = @"
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class @ClassName 
{   
@fields

    public void OnAwake(GameObject viewGO)
    {
@body1
    }

    public void OnDestroy()
    {
@body2
    }
}
";
    //緩存的所有子對象信息
    public List<UIInfo> evenlist = new List<UIInfo>();
    /// <summary>
    /// 把拼接好的腳本寫到本地。
    /// (自己可以個窗口支持改名和選擇路徑,真實工程里是帶這些功能的)
    /// </summary>
    public void WtiteClass()
    {
        bool flag = true;
        bool throwOnInvalidBytes = false;
        UTF8Encoding encoding = new UTF8Encoding(flag, throwOnInvalidBytes);
        bool append = false;
        StreamWriter writer = new StreamWriter(Application.dataPath + "/" + classname + ".cs", append, encoding);
        writer.Write(GetClasss());
        writer.Close();
        AssetDatabase.Refresh();
    }
    //腳本拼接
    public string GetClasss()
    {
        var fields = new StringBuilder();
        var body1 = new StringBuilder();
        var body2 = new StringBuilder();
        for (int i = 0; i < evenlist.Count; i++)
        {
            fields.AppendLine("\t" + evenlist[i].field);
            body1.AppendLine("\t\t" + evenlist[i].body1);
            body2.AppendLine("\t\t" + evenlist[i].body2);
        }
        template = template.Replace("@ClassName", classname).Trim();
        template = template.Replace("@body1", body1.ToString()).Trim();
        template = template.Replace("@body2", body2.ToString()).Trim();
        template = template.Replace("@fields", fields.ToString()).Trim();
        return template;
    }
}
//子對象信息
public class UIInfo{
    public string field;
    public string body1;
    public string body2;
    public UIInfo(string name, string typeKey, string path)
    {
        field = string.Format("public {0} {1};", CreateSprite.typeMap[typeKey], name);
        if (typeKey == "go")
        {
            body1 = string.Format("{0} = viewGO.transform.Find(\"{1}\").gameObject;", name, path, CreateSprite.typeMap[typeKey]);
        }
        else
        {
            body1 = string.Format("{0} = viewGO.transform.Find(\"{1}\").GetComponent<{2}>();", name, path, CreateSprite.typeMap[typeKey]);
        }
        body2 = string.Format("{0} = null;", name);
    }
}

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM