文章目录
前言
我们在写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;
}
}
}