Unity 開発にはボタンや画像などのさまざまなコンポーネントを含む多くの UI インターフェイスがあり、正しいパスに従ってそれらを見つけて保持する必要がありますが、インターフェイスが非常に大きい場合、この手順は非常に面倒ですが簡単になります。間違っている。この記事で紹介する自動コード生成ツールは、このジレンマを解決するもので、ワンクリックで必要なコンポーネントを自動的に取得して生成できるツールですので、お役に立てれば幸いです。
コード表示の生成
デザインのアイデア
オブジェクトにコードを自動的に生成させたいのですが、これは 3 つのステップにすぎません。最初のステップはオブジェクトを見つけること、2 番目のステップはコードを生成する必要があるオブジェクトのすべてのコンポーネントを記録すること、そして 3 番目のステップはファイルを作成し、記録した内容を書き込みます。
作業手順
- 必要なプレハブのインターフェイスを作成します。コンポーネント オブジェクトを取得するには、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