当前位置:   article > 正文

Unity编辑器扩展——自动生成UI界面脚本_unity ui生成

unity ui生成

一:前言

对于面板赋值或Find绑定UI组件,我们可以使用一种工具化的方式去自动生成代码并绑定对象,增加效率
分为logic和view,view层是UI界面上的组件,每次都会自动生成并覆盖,logic层是逻辑


二:使用


例如一个UI界面,我们只需要做成预制体并在Project下右键预制体,选择AutoGen/Create View则会自动生成view和logic两个脚本,logic是我们要编写逻辑的脚本,view是每次都会自动生成并覆盖的脚本


三:说明

——以下几个路径都是可以自定义的(view和logic生成的路径、view和logic模版文件的路径)


——可以自定义忽略的组件类型列表


——只会生成对象名带下划线的


四:代码实现 

  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.IO;
  5. using System.Text;
  6. using System;
  7. public class AutoGenCode
  8. {
  9. //logic层代码路径
  10. const string LogicDir = "Assets/AutoGen/Logic";
  11. //view层代码路径
  12. const string ViewDir = "Assets/AutoGen/View";
  13. //logic层模版文件路径
  14. const string LogicTempletePath = "Assets/AutoGen/LogicTemplete.txt";
  15. //view层模版文件路径
  16. const string ViewTempletePath = "Assets/AutoGen/ViewTemplete.txt";
  17. //命名空间模板
  18. const string NameSpaceTemplete = "using {0};";
  19. //字段模板
  20. const string FieldTemplete = "public {0} {1};\t";
  21. //方法模板
  22. const string MethodTemplete = "{0} = gameObject.transform.Find(\"{1}\").GetComponent<{2}>();\t\t";
  23. /// <summary>
  24. /// 忽略的组件类型列表
  25. /// </summary>
  26. static List<Type> IgnoreComponentTypeList = new List<Type>()
  27. {
  28. typeof(CanvasRenderer),
  29. typeof(RectTransform),
  30. };
  31. [MenuItem("Assets/AutoGen/Create View", priority = 0)]
  32. static void CreateLogicAndView()
  33. {
  34. GameObject go = Selection.activeGameObject;
  35. //判断是否是prefab
  36. if (PrefabUtility.GetPrefabAssetType(go) != PrefabAssetType.Regular)
  37. {
  38. Debug.LogWarning("选择的不是预制体,选择的对象:" + go.name);
  39. return;
  40. }
  41. if (!Directory.Exists(ViewDir))
  42. {
  43. Directory.CreateDirectory(ViewDir);
  44. }
  45. if (!Directory.Exists(LogicDir))
  46. {
  47. Directory.CreateDirectory(LogicDir);
  48. }
  49. string className = go.name + "View";
  50. StringBuilder fieldContent = new StringBuilder();
  51. StringBuilder methodContent = new StringBuilder();
  52. StringBuilder nameSpaceContent = new StringBuilder();
  53. nameSpaceContent.AppendLine(NameSpaceTemplete.Replace("{0}", "UnityEngine"));//必须有UnityEngine命名空间
  54. string logicTempleteContent = File.ReadAllText(LogicTempletePath, Encoding.UTF8);
  55. string viewTempleteContent = File.ReadAllText(ViewTempletePath, Encoding.UTF8);
  56. string logicPath = LogicDir + "/" + go.name + "Logic.cs";
  57. string viewPath = ViewDir + "/" + go.name + "View.cs";
  58. List<string> tempNameSpaceList = new List<string>();
  59. //计算所有子物体组件数据
  60. List<ComponentInfo> infoList = new List<ComponentInfo>();
  61. CalcComponentInfo("", go.transform, infoList);
  62. foreach (var tempInfo in infoList)
  63. {
  64. //字段
  65. string tempFieldStr = FieldTemplete.Replace("{0}", tempInfo.TypeStr);
  66. tempFieldStr = tempFieldStr.Replace("{1}", tempInfo.FieldName);
  67. fieldContent.AppendLine(tempFieldStr);
  68. //绑定方法
  69. string tempMethodStr = MethodTemplete.Replace("{0}", tempInfo.FieldName);
  70. tempMethodStr = tempMethodStr.Replace("{1}", tempInfo.Path);
  71. tempMethodStr = tempMethodStr.Replace("{2}", tempInfo.TypeStr);
  72. methodContent.AppendLine(tempMethodStr);
  73. //命名空间
  74. if (!tempNameSpaceList.Contains(tempInfo.NameSpace))
  75. {
  76. string tempNameSpaceStr = NameSpaceTemplete.Replace("{0}", tempInfo.NameSpace);
  77. tempNameSpaceList.Add(tempInfo.NameSpace);
  78. nameSpaceContent.AppendLine(tempNameSpaceStr);
  79. }
  80. }
  81. //logic层脚本
  82. if (!File.Exists(logicPath))
  83. {
  84. using (StreamWriter sw = new StreamWriter(logicPath))
  85. {
  86. string content = logicTempleteContent;
  87. content = content.Replace("#CLASSNAME#", className);
  88. sw.Write(content);
  89. sw.Close();
  90. }
  91. }
  92. //view层脚本
  93. using (StreamWriter sw = new StreamWriter(viewPath))
  94. {
  95. string content = viewTempleteContent;
  96. content = content.Replace("#NAMESPACE#", nameSpaceContent.ToString());
  97. content = content.Replace("#CLASSNAME#", className);
  98. content = content.Replace("#FIELD_BIND#", fieldContent.ToString());
  99. content = content.Replace("#METHOD_BIND#", methodContent.ToString());
  100. sw.Write(content);
  101. sw.Close();
  102. }
  103. AssetDatabase.Refresh();
  104. }
  105. /// <summary>
  106. /// 计算所有子物体组件数据
  107. /// </summary>
  108. static void CalcComponentInfo(string path, Transform child, List<ComponentInfo> infoList)
  109. {
  110. bool isRoot = string.IsNullOrEmpty(path);
  111. if (!isRoot
  112. && IsVaildField(child.name))
  113. {
  114. var componentList = child.GetComponents<Component>();
  115. foreach (var tempComponent in componentList)
  116. {
  117. ComponentInfo info = new ComponentInfo()
  118. {
  119. Path = path,
  120. go = child.gameObject,
  121. NameSpace = tempComponent.GetType().Namespace,
  122. TypeStr = tempComponent.GetType().Name,
  123. };
  124. if (!HaveSameComponentInfo(info, infoList)
  125. && !IgnoreComponentTypeList.Contains(tempComponent.GetType()))
  126. {
  127. infoList.Add(info);
  128. }
  129. }
  130. }
  131. foreach (Transform tempTrans in child.transform)
  132. {
  133. CalcComponentInfo(isRoot ? tempTrans.name : path + "/" + tempTrans.name, tempTrans.transform, infoList);
  134. }
  135. }
  136. /// <summary>
  137. /// 是否为合法的字段名
  138. /// </summary>
  139. static bool IsVaildField(string goName)
  140. {
  141. if (goName.Contains("_"))
  142. {
  143. if (int.TryParse(goName[0].ToString(), out _))
  144. {
  145. Debug.LogWarning("字段名不能以数字开头:, goName :" + goName);
  146. return false;
  147. }
  148. return true;
  149. }
  150. return false;
  151. }
  152. /// <summary>
  153. /// 是否有相同的组件数据
  154. /// </summary>
  155. static bool HaveSameComponentInfo(ComponentInfo info, List<ComponentInfo> infoList)
  156. {
  157. foreach (var tempInfo in infoList)
  158. {
  159. if (tempInfo.FieldName == info.FieldName)
  160. {
  161. Debug.LogWarning("子物体名重复:, goName :" + info.go.name);
  162. return true;
  163. }
  164. }
  165. return false;
  166. }
  167. }
  168. /// <summary>
  169. /// 组件数据
  170. /// </summary>
  171. public class ComponentInfo
  172. {
  173. public string Path;
  174. public GameObject go;
  175. public string NameSpace;
  176. public string TypeStr;
  177. public string FieldName
  178. {
  179. get
  180. {
  181. return $"{go.name}_{TypeStr}";
  182. }
  183. }
  184. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/115310
推荐阅读
相关标签
  

闽ICP备14008679号