【关于UI预制体中组件获取代码的自动生成】


前言

我们在写UI逻辑的时候,是否经常会因为写一堆又长又重复的UI组件获取的脚本而头疼呢,这个时候我们会引入一个偷懒秘籍“自动生成组件获取的代码”。


一、原理

我们会在特定的UI对象的名字后加上该对象代表的UI组件的标记符,然后通过Editor脚本拾取目标界面预制体下的所有子物体,通过识别每个子物体对象名字的标记符,自动生成获取该组件的代码,该代码的类名一般取自界面的类名,并且需要引入“partial”标识符,目的是在该界面实体类中不需要写获取组件的代码,但是可以调用到我们自动生成的组件对象。

最下面有完整代码!!

二、Editor代码

1.获取目标对象下所有的子物体

  private static void Generate(GameObject root)
  {
    
    
      m_viewGoRoot = root;
      if (root == null)
          return;
      var children = root.GetComponentsInChildren<Transform>(true);
      if (children == null || children.Length == 0)
          return;
      foreach (var item in children)
      {
    
    
          TsNeedAddInViewElement(item);
      }

      CreateDesignTemplate(_templateText);
      AssetDatabase.Refresh();
  }

2.识别子物体名称中的组件标识符

名称中的标识符可根据自己的需求定义,然后获取组件对象的预制体路径,用来生成获取组件的代码片段。

代码如下(示例):

 static void TsNeedAddInViewElement(Transform childts)
 {
    
    
     string properitystr = "";
     string tempgetCompentstr = "";
     string properityName = childts.name;
     if (childts.name.Contains("_Txt"))
     {
    
    
         tempgetCompentstr = "Text";
         properitystr = "public Text " + properityName + ";";

     }
     else if (childts.name.Contains("_Tog"))
     {
    
    
         tempgetCompentstr = "Toggle";
         properitystr = "public Toggle " + properityName + ";";
     }
     else if (childts.name.Contains("_Btn"))
     {
    
    
         tempgetCompentstr = "Button";
         properitystr = "public Button " + properityName + ";";
     }
     else if (childts.name.Contains("_RawImg"))
     {
    
    
         tempgetCompentstr = "RawImage";
         properitystr = "public RawImage " + properityName + ";";
     }
     else if (childts.name.Contains("_Img"))
     {
    
    
         tempgetCompentstr = "Image";
         properitystr = "public Image " + properityName + ";";
     }
     else if (childts.name.Contains("_Ts"))
     {
    
    
         tempgetCompentstr = "Transform";
         properitystr = "public Transform " + properityName + ";";
     }
     else if (childts.name.Contains("_RectTs"))
     {
    
    
         tempgetCompentstr = "RectTransform";
         properitystr = "public RectTransform " + properityName + ";";
     }
     else if (childts.name.Contains("_Input"))
     {
    
    
         tempgetCompentstr = "InputField";
         properitystr = "public InputField " + properityName + ";";
     }
     else if (childts.name.Contains("_Sld"))
     {
    
    
         tempgetCompentstr = "Slider";
         properitystr = "public Slider " + properityName + ";";
     }
     if (!string.IsNullOrEmpty(properitystr))
     {
    
    
         m_properityList.Add(properitystr);
         string path = GetPath(childts,m_viewGoRoot.transform);
         string tempgetCompentNameStr = string.Format(properityName + " = transform.Find(" + '"' + path + '"' + ").GetComponent<{0}>();", tempgetCompentstr);
         m_getCompentList.Add(tempgetCompentNameStr);
     }

 }

3.生成脚本

public static void CreateDesignTemplate(string templateName)
{
    
    
    Debug.Log("创建Design模版");
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("using UnityEngine.UI;");
    sb.AppendLine("using UnityEngine;");
    sb.AppendLine();
    sb.AppendLine();
    sb.AppendLine("namespace " + _path.Replace(@"/", @"."));
    sb.AppendLine("{");

    sb.AppendFormat("   public partial class {0} ", templateName + ": MonoBehaviour");
    sb.AppendLine();
    sb.AppendLine("   {");
    foreach (var item in m_properityList)
    {
    
    
        sb.AppendLine("        " + item);
    }
    sb.AppendLine();
    sb.AppendLine("        private void Awake()");
    sb.AppendLine("        {");
    foreach (var item in m_getCompentList)
    {
    
    
        sb.AppendLine("            " + item);
    }
    sb.AppendLine("        }");
    sb.AppendLine();
    sb.AppendLine("   }");
    sb.AppendLine("}");

    CreateScript(_path + @"\" + templateName + ".Design.cs", sb.ToString());
}
/// <summary>保存脚本到View目录下</summary>
private static void CreateScript(string path, string msg)
{
    
    
    StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
    sw.Write(msg);
    sw.Flush();
    sw.Close();
}

三、在Unity中使用的步骤

1.创建预制体对象,对需要获取组件的子物体添加标识符

请添加图片描述

2.点击生成扩展菜单

请添加图片描述
生成的成果:
请添加图片描述
请添加图片描述

四.完整代码

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

namespace Assets.DevFramework.Scripts.Editor
{
    
    
    /// <summary>
    /// 自动生成UI组件缓存脚本
    /// </summary>
    public class UIDesignEditor
    {
    
    
        public static GameObject m_viewGoRoot;
        public static List<string> m_properityList = new List<string>();
        public static List<string> m_getCompentList = new List<string>();

        private static string _path = "Assets/Scripts/View";
        private static string _templateText;


        [MenuItem("GameObject/UIDesign")]
        public static void AutoGetUIComponentsWindows()
        {
    
    
            var selectObj = Selection.activeObject;
            if (selectObj == null || !(selectObj is GameObject gameObj))
            {
    
    
                EditorUtility.DisplayDialog("警告!", "请先选中界面预制体!", "确定");
                return;
            }
            _templateText = selectObj.name;

            _path = _path + "/" + _templateText;
            if (!Directory.Exists(_path))
            {
    
    
                Directory.CreateDirectory(_path);
            }
            m_viewGoRoot = (GameObject)selectObj;
            Generate(m_viewGoRoot);
        }


        private static void Generate(GameObject root)
        {
    
    
            m_viewGoRoot = root;
            if (root == null)
                return;
            var children = root.GetComponentsInChildren<Transform>(true);
            if (children == null || children.Length == 0)
                return;
            foreach (var item in children)
            {
    
    
                TsNeedAddInViewElement(item);
            }

            CreateDesignTemplate(_templateText);
            AssetDatabase.Refresh();
        }

        static void TsNeedAddInViewElement(Transform childts)
        {
    
    
            string properitystr = "";
            string tempgetCompentstr = "";
            string properityName = childts.name;
            if (childts.name.Contains("_Txt"))
            {
    
    
                tempgetCompentstr = "Text";
                properitystr = "public Text " + properityName + ";";

            }
            else if (childts.name.Contains("_Tog"))
            {
    
    
                tempgetCompentstr = "Toggle";
                properitystr = "public Toggle " + properityName + ";";
            }
            else if (childts.name.Contains("_Btn"))
            {
    
    
                tempgetCompentstr = "Button";
                properitystr = "public Button " + properityName + ";";
            }
            else if (childts.name.Contains("_RawImg"))
            {
    
    
                tempgetCompentstr = "RawImage";
                properitystr = "public RawImage " + properityName + ";";
            }
            else if (childts.name.Contains("_Img"))
            {
    
    
                tempgetCompentstr = "Image";
                properitystr = "public Image " + properityName + ";";
            }
            else if (childts.name.Contains("_Ts"))
            {
    
    
                tempgetCompentstr = "Transform";
                properitystr = "public Transform " + properityName + ";";
            }
            else if (childts.name.Contains("_RectTs"))
            {
    
    
                tempgetCompentstr = "RectTransform";
                properitystr = "public RectTransform " + properityName + ";";
            }
            else if (childts.name.Contains("_Input"))
            {
    
    
                tempgetCompentstr = "InputField";
                properitystr = "public InputField " + properityName + ";";
            }
            else if (childts.name.Contains("_Sld"))
            {
    
    
                tempgetCompentstr = "Slider";
                properitystr = "public Slider " + properityName + ";";
            }
            if (!string.IsNullOrEmpty(properitystr))
            {
    
    
                m_properityList.Add(properitystr);
                string path = GetPath(childts,m_viewGoRoot.transform);
                string tempgetCompentNameStr = string.Format(properityName + " = transform.Find(" + '"' + path + '"' + ").GetComponent<{0}>();", tempgetCompentstr);
                m_getCompentList.Add(tempgetCompentNameStr);
            }

        }

        public static void CreateDesignTemplate(string templateName)
        {
    
    
            Debug.Log("创建Design模版");
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using UnityEngine.UI;");
            sb.AppendLine("using UnityEngine;");
            sb.AppendLine();
            sb.AppendLine();
            sb.AppendLine("namespace " + _path.Replace(@"/", @"."));
            sb.AppendLine("{");

            sb.AppendFormat("   public partial class {0} ", templateName + ": MonoBehaviour");
            sb.AppendLine();
            sb.AppendLine("   {");
            foreach (var item in m_properityList)
            {
    
    
                sb.AppendLine("        " + item);
            }
            sb.AppendLine();
            sb.AppendLine("        private void Awake()");
            sb.AppendLine("        {");
            foreach (var item in m_getCompentList)
            {
    
    
                sb.AppendLine("            " + item);
            }
            sb.AppendLine("        }");
            sb.AppendLine();
            sb.AppendLine("   }");
            sb.AppendLine("}");

            CreateScript(_path + @"\" + templateName + ".Design.cs", sb.ToString());
        }
        /// <summary>保存脚本到View目录下</summary>
        private static void CreateScript(string path, string msg)
        {
    
    
            StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
            sw.Write(msg);
            sw.Flush();
            sw.Close();
        }

        private static string GetPath(Transform obj, Transform root)
        {
    
    
            string path = "/" + obj.name;
            while (obj.transform.parent != root)
            {
    
    
                obj = obj.transform.parent;
                path = "/" + obj.name + path;
            }
            if (path.StartsWith("/"))
                path = path.Remove(0, 1);
            return path;
        }
    }
}


猜你喜欢

转载自blog.csdn.net/weixin_43559607/article/details/134016605