Unity之自动生成预制体脚本
Posted 彩色墨水
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity之自动生成预制体脚本相关的知识,希望对你有一定的参考价值。
在Unity开发中有许许多多的UI界面,包含着不同的组件,比如Button、Image等,我们需要按正确的路径找到它们并持有它们,这个步骤在界面十分庞大的时候,会十分繁琐易错。本文介绍的自动生成代码工具就是为了解决这一困境,可以自动获取那些我们想要的组件,一键生成,希望对你有所帮助。
生成代码展示
设计思路
我们要使得对象自动生成代码,无非就是分三步,第一步找到这个对象,第二步记录这个对象身上所有需要生成代码的组件,第三步创建一份文件写入我们记录好的内容。
操作流程
- 制作好我们需要的预制体界面,要获取组件的对象用T_来开头
- 右键界面根节点,点击SpawnUICode(生成UI模板),会弹出操作窗口
- 点击窗口的选择脚本要生成的模块,会弹出我们预设的模块下拉菜单,选择我们对应的模块,即可将脚本生成在选中的模块下。
源码
弹出窗口代码
class GeneratePathSelectWindow : EditorWindow
private string[] path = new string[]
"Common",
"Store",
"Role",
"Host",
;
private static GameObject selectGo;
public void ShowWindow(GameObject go)
selectGo = go;
EditorWindow.GetWindow(typeof(GeneratePathSelectWindow));
void OnGUI()
if (GUILayout.Button("选择脚本要生成的模块"))
ShowGenericMenu();
private void ShowGenericMenu()
GenericMenu menu = new GenericMenu(); //初始化GenericMenu
for (int i = 0; i < path.Length; i++)
menu.AddItem(new GUIContent(path[i]), false, SelectPath, path[i]); //向菜单中添加菜单项
menu.ShowAsContext(); //显示菜单
void SelectPath(object floderName)
string t = floderName.ToString();
Debug.Log("选择路径:" + floderName);
UICodeSpawner.SpawnUICode(selectGo, t);//生成脚本代码
内容写入代码
private static void SpawnPanelCode(GameObject gameObject)
Path2WidgetCachedDict?.Clear();
Path2WidgetCachedDict = new Dictionary<string, List<Component>>();
FindAllWidgets(gameObject.transform, "");
SpawnCodeForPanel(gameObject);
AssetDatabase.Refresh();
private static void SpawnCodeForPanel(GameObject gameObject)
var strPanelName = gameObject.name;
var strFilePath = Application.dataPath + defaultUIPath + selectFolderName + "/UIBehaviour/" + strPanelName;
if (!Directory.Exists(strFilePath))
Debug.LogError("请先(SpawnerUICode)生成UI代码模板");
Directory.CreateDirectory(strFilePath);
return;
SpawnCodeForPanelComponentBehaviour(gameObject);
private static void SpawnCodeForPanelComponentBehaviour(GameObject gameObject)
if (null == gameObject)
return;
string strDlgName = gameObject.name;
string strDlgComponentName = gameObject.name + "View";
string strFilePath = Application.dataPath + defaultUIPath + selectFolderName + "/UIBehaviour/" + strDlgName;
if (!Directory.Exists(strFilePath))
Directory.CreateDirectory(strFilePath);
strFilePath = Application.dataPath + defaultUIPath + selectFolderName + "/UIBehaviour/" + strDlgName +
"/" + strDlgComponentName + ".cs";
StreamWriter sw = new StreamWriter(strFilePath, false, Encoding.UTF8);
StringBuilder strBuilder = new StringBuilder();
strBuilder.AppendLine("using UnityEngine;");
strBuilder.AppendLine("using UnityEngine.UI;");
strBuilder.AppendLine();
strBuilder.AppendLine("namespace AutoBuildCode");
strBuilder.AppendLine("");
strBuilder.AppendLine("\\t/// <summary>");
strBuilder.AppendLine("\\t/// 此文件为脚本自动生成并且覆盖;");
strBuilder.AppendLine("\\t/// 非必要请不要在此作修改");
strBuilder.AppendLine("\\t/// </summary>");
strBuilder.AppendFormat("\\tpublic class 0 : MonoBehaviour \\r\\n", strDlgComponentName)
.AppendLine("\\t");
strBuilder.AppendFormat("\\t\\tprivate Transform uiTransform = null;\\r\\n");
CreateDeclareCode(ref strBuilder);
strBuilder.AppendLine();
CreateWidgetBindCode(ref strBuilder, gameObject.transform);
CreateDestroyWidgetCode(ref strBuilder);
strBuilder.AppendLine("\\t");
strBuilder.AppendLine("");
sw.Write(strBuilder);
sw.Flush();
sw.Close();
private static void CreateDestroyWidgetCode(ref StringBuilder strBuilder)
strBuilder.AppendFormat("\\t\\tpublic void DestroyWidget()");
strBuilder.AppendLine("\\n\\t\\t");
CreateDlgWidgetDisposeCode(ref strBuilder);
strBuilder.AppendFormat("\\t\\t\\tthis.uiTransform = null;\\r\\n");
strBuilder.AppendLine("\\t\\t\\n");
private static void CreateDlgWidgetDisposeCode(ref StringBuilder strBuilder, bool isSelf = false)
string pointStr = isSelf ? "self" : "this";
foreach (KeyValuePair<string,List<Component>> pair in Path2WidgetCachedDict)
foreach (var info in pair.Value)
Component widget = info;
string strClassType = widget.GetType().ToString();
string widgetName = widget.name + strClassType.Split('.').ToList().Last();
strBuilder.AppendFormat("\\t\\t 0.m_1 = null;\\r\\n", pointStr, widgetName);
private static void CreateWidgetBindCode(ref StringBuilder strBuilder, Transform transRoot)
foreach (KeyValuePair<string, List<Component>> pair in Path2WidgetCachedDict)
foreach (var info in pair.Value)
Component widget = info;
string strPath = GetWidgetPath(widget.transform, transRoot);
string strClassType = widget.GetType().ToString();
string strInterfaceType = strClassType;
string widgetName = widget.name + strClassType.Split('.').ToList().Last();
strBuilder.AppendFormat(" public 0 1\\r\\n", strInterfaceType, widgetName);
strBuilder.AppendLine(" ");
strBuilder.AppendLine(" get");
strBuilder.AppendLine(" ");
strBuilder.AppendFormat(" if( this.m_0 == null )\\n", widgetName);
strBuilder.AppendLine(" ");
strBuilder.AppendFormat(
" this.m_0 = transform.Find(\\"1\\").GetComponent<2>();\\r\\n",
widgetName, strPath, strInterfaceType);
strBuilder.AppendLine(" ");
strBuilder.AppendFormat(" return this.m_0;\\n", widgetName);
strBuilder.AppendLine(" ");
strBuilder.AppendLine(" \\n");
static string GetWidgetPath(Transform obj, Transform root)
string path = obj.name;
while (obj.parent != null && obj.parent != root)
obj = obj.transform.parent;
path = obj.name + "/" + path;
return path;
private static void CreateDeclareCode(ref StringBuilder strBuilder)
foreach (KeyValuePair<string, List<Component>> pair in Path2WidgetCachedDict)
foreach (var info in pair.Value)
Component widget = info;
string strClassType = widget.GetType().ToString();
string widgetName = widget.name + strClassType.Split('.').ToList().Last();
strBuilder.AppendFormat("\\t\\tprivate 0 m_1=null;\\r\\n", strClassType, widgetName);
/// <summary>
/// 把所有的组件配置都装好了,装在了Path2WidgetCachedDict
/// </summary>
/// <param name="trans"></param>
/// <param name="strPath"></param>
private static void FindAllWidgets(Transform trans, string strPath)
if (null == trans)
return;
for (int nIndex = 0; nIndex < trans.childCount; ++nIndex) //只算儿子,不算孙子
Transform child = trans.GetChild(nIndex);
string strTemp = strPath + "/" + child.name;
bool isSubUI = child.name.StartsWith(CommonUIPrefix);
if (child.name.StartsWith(UIWidgetPrefix))
foreach (var uiComponent in WidgetInterfaceList)
Component component = child.GetComponent(uiComponent);
if (null == component)
continue;
if (Path2WidgetCachedDict.ContainsKey(child.name))
Path2WidgetCachedDict[child.name].Add(component);
continue;
List<Component> componentsList = new List<Component>();
componentsList.Add(component);
Path2WidgetCachedDict.Add(child.name, componentsList);
if (isSubUI)
Debug.Log($"遇到子UI,child.name,不生成子UI项代码");
continue;
FindAllWidgets(child, strTemp);
static UICodeSpawner()
WidgetInterfaceList = new List<string>();
WidgetInterfaceList.Add("Button");
WidgetInterfaceList.Add("Text");
WidgetInterfaceList.Add("TMP_Text");
WidgetInterfaceList.Add("InputField");
WidgetInterfaceList.Add("TMP_InputField");
WidgetInterfaceList.Add("Dropdown");
WidgetInterfaceList.Add("TMP_Dropdown");
WidgetInterfaceList.Add("Input");
WidgetInterfaceList.Add("Scrollbar");
WidgetInterfaceList.Add("ToggleGroup");
WidgetInterfaceList.Add("Toggle");
WidgetInterfaceList.Add("Slider");
WidgetInterfaceList.Add("ScrollRect");
WidgetInterfaceList.Add("Image");
WidgetInterfaceList.Add("RawImage");
WidgetInterfaceList.Add("Canvas");
WidgetInterfaceList.Add("CanvasGroup");
工程项目
链接:https://pan.baidu.com/s/1yToMdgKa1AxsbfWrqu8YMA
提取码:vabd
以上是关于Unity之自动生成预制体脚本的主要内容,如果未能解决你的问题,请参考以下文章