代码生成参考的 知乎【Unity】工具类系列教程—— 代码自动化生成! - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/30716595
操作流程:
一,创建模块
这里只写了创建UI预制体(模板UI)和对应脚本,而且放在一个文件夹下的.
正式项目一般一个模块会有多个脚本与之对应(数据,逻辑,UI),而且预制体和脚本也是分开存放;
具体看项目框架结构,这里只是一个模拟;
完成后会在对应目录生成一个.cs脚本和预制体
预制体是通过模板预制体拷贝过去修改名字实现的,所以需要先有一个 模板UI,我的模板很简单,就一个canvas+mask+root
二,完成基本的脚本和预制体生成后,就可以去修改预制体(就是拼界面);
这里要注意的是,需要用脚本访问的组件,名字需要根据组件类型特殊处理:
这里的主逻辑就是参考的上面知乎帖子,里面写的很详细了,有疑问的可以跳过去看看;
三,实现你自己的界面逻辑... 是的,没有了
具体代码贴出来,写得有点凌乱, 后续有时间再优化吧...
2022.2.24更新-------------
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
public class AutoModule : EditorWindow
{
static string moduleName;//模块名
//代码模板----------------------------
public static string UIClass =
@"using UnityEngine;
using UnityEngine.UI;
using System;
public class #类名# : MonoBehaviour
{
//auto
//#成员#
void Awake()
{
}
void Start()
{
//#查找#
}
}
";
public static string DataClass =
@"using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class #类名#Data
{
static #类名#Data _instance = null;
public static #类名#Data GetInstance
{
get
{
if (_instance == null)
{
_instance = new #类名#Data();
}
return _instance;
}
}
}";
//代码模板----------------------------
[MenuItem("自动化/打开模块生成从窗口",false)]
public static void CreateWindow()
{
var rect = new Rect(900, 600, 400, 600);
GetWindowWithRect(typeof(AutoModule), rect, true,"创建模块");
}
private void OnGUI()
{
GUILayout.BeginVertical();
//GUILayout.BeginHorizontal();
GUILayout.Label("模块名(脚本名)");
moduleName = GUILayout.TextField(moduleName);
GUILayout.Space(10);
if (GUILayout.Button("生成模块"))
{
if (string.IsNullOrEmpty(moduleName))
{
Debug.LogError("模块名不能为空");
return;
}
bool rightName = Regex.IsMatch(moduleName, @"^[a-zA-Z_][A-Za-z0-9_]*$");
if (!rightName)
{
Debug.LogError("注意命名规则");
return;
}
//生成预制体
CreateUIPrefab();
//生成脚本
CreateScript();
//预制体绑定脚本
//GameObject t = null;
//t.AddComponent<> ();
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
//GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
//生成对应的脚本文件夹
static string GetModleFolder(string folderName)
{
string path = Application.dataPath + "/MyProject/" + folderName;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
//生成预制体
static void CreateUIPrefab()
{
string templateUI = Application.dataPath + "/MyProject/TemplateUI/UI.Prefab";
string templateUIMeta = templateUI + ".meta";
//需要同时处理预制体和对应的.meta文件
string moveTo = GetModleFolder(moduleName) + "/" + moduleName + "UI.prefab";
string metaMoveTo = moveTo + ".meta";
if (File.Exists(moveTo))
{
Debug.LogError("该目录下已存在同名预制体!");
return;
}
//拷贝
FileUtil.CopyFileOrDirectory(templateUI, moveTo);
FileUtil.CopyFileOrDirectory(templateUIMeta, metaMoveTo);
Debug.Log("生成预制体成功");
}
static void CreateScript()
{
//ui脚本
string scriptPath = GetModleFolder(moduleName) + "/" + moduleName + ".cs";
//数据脚本
string scriptPath1 = GetModleFolder(moduleName) + "/" + moduleName + "Data.cs";
if (File.Exists(scriptPath) || File.Exists(scriptPath1))
{
Debug.LogError("该目录下已存在同名脚本!");
return;
}
string classStrUI = UIClass;
classStrUI = classStrUI.Replace("#类名#", moduleName);
string classStrData = DataClass;
classStrData = classStrData.Replace("#类名#", moduleName);
FileStream file1 = new FileStream(scriptPath, FileMode.CreateNew);
FileStream file2 = new FileStream(scriptPath1, FileMode.CreateNew);
StreamWriter fileW1 = new StreamWriter(file1, System.Text.Encoding.UTF8);
fileW1.Write(classStrUI);
fileW1.Flush();
fileW1.Close();
file1.Close();
StreamWriter fileW2 = new StreamWriter(file2, System.Text.Encoding.UTF8);
fileW2.Write(classStrData);
fileW2.Flush();
fileW2.Close();
file2.Close();
Debug.Log("创建脚本 " + moduleName + ".cs 成功!");
Debug.Log("创建脚本 " + moduleName + "Data.cs 成功!");
}
[MenuItem("自动化/更新UI脚本")]
public static void UpdateUIScript()
{
var dicUIType = new Dictionary();
dicUIType.Add("Image", "Image");
dicUIType.Add("Button", "Button");
dicUIType.Add("Text", "Text");
dicUIType.Add("Tran", "Transform");
GameObject[] selectobjs = Selection.gameObjects;
if (selectobjs == null || selectobjs.Length <= 0)
{
Debug.LogError("未选中预制体");
return;
}
foreach (GameObject go in selectobjs)
{
//选择的物体
GameObject selectobj = go.transform.root.gameObject;
//物体的子物体
Transform[] _transforms = selectobj.GetComponentsInChildren(true);
List childList = new List(_transforms);
//UI需要查询的物体
var mainNode = from trans in childList where trans.name.Contains('_') && dicUIType.Keys.Contains(trans.name.Split('_')[0]) select trans;
var nodePathList = new Dictionary();
//循环得到物体路径
foreach (Transform node in mainNode)
{
Transform tempNode = node;
string nodePath = "/" + tempNode.name;
while (tempNode != tempNode.root)
{
tempNode = tempNode.parent;
int index = nodePath.IndexOf('/');
nodePath = nodePath.Insert(index, "/" + tempNode.name);
}
nodePathList.Add(node.name, nodePath);
}
//成员变量字符串
string memberstring = "";
//查询代码字符串
string loadedcontant = "";
foreach (Transform itemtran in mainNode)
{
string typeStr = dicUIType[itemtran.name.Split('_')[0]];
memberstring += "public " + typeStr + " " + itemtran.name + ";\r\n\t";
loadedcontant += itemtran.name + " = " + "gameObject.transform.Find(\"" + nodePathList[itemtran.name] + "\").GetComponent<" + typeStr + ">();\r\n\t\t";
}
string module = selectobj.name.Substring(0, selectobj.name.Length - 2);//去掉"UI",得到模块名;
string scriptPath = GetModleFolder(module) + "/" + module + ".cs";
string classStr = "";
//如果已经存在了脚本,则替换需要的地方
if (File.Exists(scriptPath))
{
FileStream classfile = new FileStream(scriptPath, FileMode.Open);
StreamReader read = new StreamReader(classfile);
classStr = read.ReadToEnd();
if (string.IsNullOrEmpty(loadedcontant) || string.IsNullOrEmpty(memberstring))
{
read.Close();
classfile.Close();
Debug.Log("没有可以替换的内容");
return;
}
classStr = classStr.Replace("//#查找#", loadedcontant);
classStr = classStr.Replace("//#成员#", memberstring);
read.Close();
classfile.Close();
FileStream file = new FileStream(scriptPath, FileMode.Open);
StreamWriter fileW = new StreamWriter(file, System.Text.Encoding.UTF8);
fileW.Write(classStr);
fileW.Flush();
fileW.Close();
file.Close();
}
Debug.Log("更新脚本 " + selectobj.name + ".cs 成功!");
//刷新,保存
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
}
}
2022.2.24----更新内容------
加入了模块Data脚本的创建, 主要是CreateScript方法里的功能;