• 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("	" + evenlist[i].field);
                body1.AppendLine("		" + evenlist[i].body1);
                body2.AppendLine("		" + 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);
        }
    }

      

  • 相关阅读:
    ASP.NET MVC 学习: 视图
    翻译:ASP.NET MVC Example Application over Northwind with Entity Framework
    主流web2.0网站的配色参考方案
    jQuery1.2选择器
    ASP.NET MVC URL Routing 学习
    [转]关于DOM元素定位属性的深入学习
    ASP.NET MVC : Action过滤器(Filtering)
    【翻译】使用ASP.NET MVC 和LINQ建立一个简单的博客 Part 3
    Windows 8开发者训练营第一日来自现场的图片报道
    从数据到信息到决策
  • 原文地址:https://www.cnblogs.com/lihangppz/p/8934091.html
Copyright © 2020-2023  润新知