using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using YouYou;

namespace JiangHu.Tools
{
    public class CreateUIScriptTool
    {
        [MenuItem("Assets/生成UI脚本",false,10000)]  //注释看下面Cell
        public static void CreateUIScript()
        {
            var gameObject = Selection.activeGameObject;
            if (gameObject == null)
            {
                GameEntry.LogError("请选中预制体!");
                return;
            }
            if (!gameObject.name.StartsWith("UI"))
            {
                GameEntry.LogError("自动生成代码必须是以UI开头的UI预制体!");
                return;
            }
            string templateDesignPath = "/Game/YouYouScript/Editor/UITemplateDesign.txt";
            string templatePath = "/Game/YouYouScript/Editor/UITemplate.txt";

            string prefabPath = "Assets/Download/UI/UIPrefab";
            var directoryInfo = new DirectoryInfo(prefabPath);

            List<GameObject> needBindList = new List<GameObject>();
            foreach(var component in gameObject.GetComponentsInChildren<UIBind>())
            {
                needBindList.Add(component.gameObject);
            }

            foreach (var file in directoryInfo.GetFileSystemInfos("*", SearchOption.AllDirectories))
            {
                if (file.Extension.Equals(".prefab"))
                {
                    string name = file.Name.Substring(0, gameObject.name.Length);
                    if (name == gameObject.name)
                    {
                        string scriptDirName = file.FullName.Substring(Application.dataPath.Length + prefabPath.Length - 5);
                        scriptDirName = scriptDirName.Substring(0, scriptDirName.Length - file.Name.Length - 1);

                        string scriptPath = Application.dataPath + "/Game/YouYouScript/UI/" + scriptDirName;
                        if (!Directory.Exists(scriptPath))
                        {
                            Directory.CreateDirectory(scriptPath);
                            Debug.Log("文件夹创建成功!");
                        }

                        string scriptStr = GetTemplateDesignText(name, needBindList, templateDesignPath);
                        using (FileStream fs = new FileStream(string.Format("{0}/{1}.Design.cs", scriptPath, name), FileMode.Create))
                        {
                            using (StreamWriter sw = new StreamWriter(fs))
                            {
                                sw.Write(scriptStr.ToString());
                                Debug.Log("绑定关系生成成功!");
                            }
                        }

                        string scriptName = scriptPath + "/" + name + ".cs";
                        if (!File.Exists(scriptName))
                        {
                            scriptStr = GetTemplateText(name, needBindList, templatePath);
                            using (FileStream fs = new FileStream(string.Format("{0}/{1}.cs", scriptPath, name), FileMode.Create))
                            {
                                using (StreamWriter sw = new StreamWriter(fs))
                                {
                                    sw.Write(scriptStr.ToString());
                                    Debug.Log("业务代码生成成功!仍需手动将代码文件拖到预制体上!");
                                }
                            }
                        }

                        //回收资源
                        System.GC.Collect();
                        //刷新编辑器
                        AssetDatabase.Refresh();
                    }
                }
            }
        }

        /// <summary>
        /// 生成业务代码
        /// </summary>
        public static string GetTemplateText(string scriptName, List<GameObject> needBindList, string templatePath)
        {
            //读取文本全部内容
            string designCode = File.ReadAllText(Application.dataPath + templatePath);

            //循环添加OnClick方法文本
            string btnOnClickStr = string.Empty;
            foreach (var go in needBindList)
            {
                if (go.GetComponent<Button>() != null)
                {
                    btnOnClickStr += "        private void OnClick_" + go.name + "()\r\n        {\r\n            Log(\"点击了" + go.name + "\");\r\n        }\r\n";
                    continue;
                }
            }

            //替换文本
            designCode = designCode.Replace("#ClassName", scriptName)
            .Replace("#BtnOnClick", btnOnClickStr)
            .Replace("#Time", DateTime.Now.ToString());

            return designCode;
        }

        /// <summary>
        /// 生成绑定关系
        /// </summary>
        public static string GetTemplateDesignText(string scriptName, List<GameObject> needBindList,string templateDesignPath)
        {
            //读取文本全部内容
            string designCode = File.ReadAllText(Application.dataPath + templateDesignPath);

            //循环添加组件初始化 组件绑定 按钮绑定
            string initComponentStr = string.Empty;
            string bindComponentStr = string.Empty;
            string btnOnClickStr = string.Empty;
            foreach (var go in needBindList)
            {
                var bind = go.GetComponent<UIBind>();
                var name = go.name;
                if(bind == null)
                {
                    continue;
                }
                bindComponentStr += "            " + name + " = rectTransform.Find(\"" + FindComponentInPrefabPath(scriptName, go) + "\").GetComponent<" + bind.BindComponent.GetType() + ">();\r\n";
                initComponentStr += "\r\n        /// <summary>\r\n        /// " + bind.Content + "\r\n        /// </summary>";
                initComponentStr += "\r\n        private " + bind.BindComponent.GetType() + " " + name + ";\r\n";

                if (go.GetComponent<Button>() != null)
                {
                    btnOnClickStr += "            " + name + ".onClick.AddListener(OnClick_" + name + ");\r\n";
                }
            }

            //替换文本
            designCode = designCode.Replace("#ClassName", scriptName)
            .Replace("#InitComponent", initComponentStr)
            .Replace("#BindComponent", bindComponentStr)
            .Replace("#BtnAddOnClick", btnOnClickStr)
            .Replace("#Time", DateTime.Now.ToString());

            return designCode;
        }

        /// <summary>
        /// 循环父物体拿到组件路径
        /// </summary>
        private static string FindComponentInPrefabPath(string scriptName, GameObject go)
        {
            //拿到父物体 修改路径 设置跳出值
            var parentGo = go.transform.parent;
            string path = parentGo.name + "/" + go.name;
            bool isParent = true;

            while (isParent)
            {
                //如果父物体名字等于传进来的对象名 就退出
                if (parentGo.name == scriptName)
                {
                    isParent = false;
                    break;
                }

                //循环添加路径
                parentGo = parentGo.transform.parent;
                path = parentGo.name + "/" + path;
            }

            //删除最上级物体名
            path = path.Substring(parentGo.name.Length + 1);

            return path;
        }

        [MenuItem("Assets/生成Cell脚本", false, 10000)]
        public static void CreateCellScript()
        {
            //获取选中物体对象 判断是否为Cell
            var gameObject = Selection.activeGameObject;
            if (gameObject == null)
            {
                GameEntry.LogError("请选中预制体!");
                return;
            }
            if (!gameObject.name.EndsWith("Cell"))
            {
                GameEntry.LogError("自动生成代码必须是以Cell结尾的Cell预制体!");
                return;
            }

            //模板路径
            string templateDesignPath = "/Game/YouYouScript/Editor/TemplateDesignCell.txt";
            string templatePath = "/Game/YouYouScript/Editor/TemplateCell.txt";
            //UI路径
            string prefabPath = "Assets/Download/UI/UIPrefab";
            var directoryInfo = new DirectoryInfo(prefabPath);

            //循环添加绑定组件
            List<GameObject> needBindList = new List<GameObject>();
            foreach (var component in gameObject.GetComponentsInChildren<UIBind>())
            {
                needBindList.Add(component.gameObject);
            }

            //循环找到对应的预制体路径
            foreach (var file in directoryInfo.GetFileSystemInfos("*", SearchOption.AllDirectories))
            {
                //找到预制体
                if (file.Extension.Equals(".prefab"))
                {
                    string name = file.Name.Substring(0, gameObject.name.Length);
                    //如果是选中的预制体
                    if (name == gameObject.name)
                    {
                        //拿到文件夹名字
                        string scriptDirName = file.FullName.Substring(Application.dataPath.Length + prefabPath.Length - 5);
                        scriptDirName = scriptDirName.Substring(0, scriptDirName.Length - file.Name.Length - 1);

                        //拿到文件夹路径
                        string scriptPath = Application.dataPath + "/Game/YouYouScript/UI/" + scriptDirName;
                        //如果没有就创建
                        if (!Directory.Exists(scriptPath))
                        {
                            Directory.CreateDirectory(scriptPath);
                            Debug.Log(scriptDirName+"文件夹创建成功!");
                        }

                        //生成绑定关系
                        string scriptStr = GetTemplateDesignText(name, needBindList, templateDesignPath);
                        using (FileStream fs = new FileStream(string.Format("{0}/{1}.Design.cs", scriptPath, name), FileMode.Create))
                        {
                            using (StreamWriter sw = new StreamWriter(fs))
                            {
                                sw.Write(scriptStr.ToString());
                                Debug.Log("绑定关系生成成功!");
                            }
                        }

                        //生成业务代码
                        string scriptName = scriptPath + "/" + name + ".cs";
                        //如果不存在才创建
                        if (!File.Exists(scriptName))
                        {
                            scriptStr = GetTemplateText(name, needBindList, templatePath);
                            using (FileStream fs = new FileStream(string.Format("{0}/{1}.cs", scriptPath, name), FileMode.Create))
                            {
                                using (StreamWriter sw = new StreamWriter(fs))
                                {
                                    sw.Write(scriptStr.ToString());
                                    Debug.Log("业务代码生成成功!仍需手动将代码拖到预制体上!");
                                }
                            }
                        }

                        //回收资源
                        System.GC.Collect();
                        //刷新编辑器
                        AssetDatabase.Refresh();
                    }
                }
            }
        }
    }
}

using System.IO;
using UnityEditor;
using UnityEngine;

namespace Framework
{
    /// <summary>
    /// UI代码生成
    /// </summary>
    public class GenerateUIScript : Editor
    {
        [MenuItem("GameObject/Generate UI", false, 10000)]
        public static void GenerateUI()
        {
            var go = Selection.activeGameObject;
            if (go == null || !go.name.Contains("UI"))
            {
                Debug.LogError(go.name + " 不是UI!");
                return;
            }

            //寻找到当前obj的路径
            var directoryInfo = new DirectoryInfo(Application.dataPath);
            string prefabName = go.name + ".prefab";
            string path = string.Empty;
            foreach (var item in directoryInfo.GetFiles("*.*", SearchOption.AllDirectories))
            {
                if (item.Name == prefabName)
                {
                    //预制体路径
                    path = item.FullName;
                    //替换成脚本路径
                    path = path.Replace("GameData\\Prefabs", "GameData\\Scripts").Substring(0, path.Length - prefabName.Length);
                    break;
                }
            }

            //创建目录
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            CreateUIScript(go, path);
            CreateUIDesignScript(go, path);

            Debug.Log(go.name + "生成完毕!");
            //回收资源
            System.GC.Collect();
            //刷新编辑器
            AssetDatabase.Refresh();
        }

        private static void CreateUIScript(GameObject go, string path)
        {
            string temp = @"using Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace GameData
{
    public partial class #UIName : UIBase
    {
        public override void OnInit()
        {
            
        }

        public override void OnShow(params object[] args)
        {
            
        }

        public override void OnBeforDestroy()
        {
            
        }
    }
}
";

            var scripts = File.CreateText(path + go.name + ".cs");
            temp = temp.Replace("#UIName", go.name);
            scripts.Write(temp);
            scripts.Close();
        }

        private static void CreateUIDesignScript(GameObject go, string path)
        {
            string temp = @"/*********************************************
 * 自动生成代码,禁止手动修改文件
 * 脚本名:#UIName.Design.cs
 * 修改时间:#Time
 *********************************************/

using Framework;
using UnityEngine;
using UnityEngine.UI;

namespace GameData
{
    public partial class #UIName : UIBase
    {#Component
        public override void OnCreate()
        {
            rectTransform = gameobject.GetComponent<RectTransform>();
            #Find
        }
    }
}
";
            string componentStr = @"
        /// <summary>
        /// #Remark
        /// </summary>
        private #Component #Name;
";
            string FindStr = "#Name = rectTransform.Find(\"#Path\").GetComponent<#Component>();";

            var componentArr = go.GetComponentsInChildren<UIBind>();
            var newComponentStr = string.Empty;
            var newFindStr = string.Empty;
            for (int i = 0; i < componentArr.Length; i++)
            {
                //声明变量
                var tempComponentStr = componentStr.Replace("#Component", componentArr[i].Obj.GetType().ToString());
                tempComponentStr = tempComponentStr.Replace("#Name", componentArr[i].Obj.name);
                tempComponentStr = tempComponentStr.Replace("#Remark", componentArr[i].Remark);
                newComponentStr += tempComponentStr;

                //寻找对象
                var tempFindStr = FindStr.Replace("#Component", componentArr[i].Obj.GetType().ToString());
                tempFindStr = tempFindStr.Replace("#Name", componentArr[i].Obj.name);
                tempFindStr = tempFindStr.Replace("#Path", FindComponentInPrefabPath(go.name,componentArr[i].gameObject));
                tempFindStr += "\r\n\t\t\t";
                newFindStr += tempFindStr;
            }

            //创建对象
            var scripts = File.CreateText(path + go.name + ".Design.cs");
            //文本替换
            temp = temp.Replace("#UIName", go.name);
            temp = temp.Replace("#Time", System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
            temp = temp.Replace("#Component", newComponentStr);
            temp = temp.Replace("#Find", newFindStr);
            scripts.Write(temp);
            scripts.Close();
        }

        /// <summary>
        /// 循环父物体拿到组件路径
        /// </summary>
        private static string FindComponentInPrefabPath(string scriptName,GameObject go)
        {
            //拿到父物体 修改路径 设置跳出值
            var parentGo = go.transform.parent;
            string path = parentGo.name + "/" + go.name;
            bool isParent = true;

            while (isParent)
            {
                //如果父物体名字等于传进来的对象名 就退出
                if (parentGo.name == scriptName)
                {
                    isParent = false;
                    break;
                }

                //循环添加路径
                parentGo = parentGo.transform.parent;
                path = parentGo.name + "/" + path;
            }

            //删除最上级物体名
            path = path.Substring(parentGo.name.Length + 1);

            return path;
        }
    }
}

最后修改:2024 年 05 月 29 日
如果觉得我的文章对你有用,请随意赞赏