IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity 自动化1.0(代码预制体生成到指定模块) -> 正文阅读

[游戏开发]Unity 自动化1.0(代码预制体生成到指定模块)

代码生成参考的 知乎【Unity】工具类系列教程—— 代码自动化生成! - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/30716595

操作流程:

一,创建模块

这里只写了创建UI预制体(模板UI)和对应脚本,而且放在一个文件夹下的.

正式项目一般一个模块会有多个脚本与之对应(数据,逻辑,UI),而且预制体和脚本也是分开存放;

具体看项目框架结构,这里只是一个模拟;

完成后会在对应目录生成一个.cs脚本和预制体

?预制体是通过模板预制体拷贝过去修改名字实现的,所以需要先有一个 模板UI,我的模板很简单,就一个canvas+mask+root

? ? ? ?

二,完成基本的脚本和预制体生成后,就可以去修改预制体(就是拼界面);

这里要注意的是,需要用脚本访问的组件,名字需要根据组件类型特殊处理:

?界面弄好后,选中这个预制体,然后点击? ?[更新UI脚本]?

?这里的主逻辑就是参考的上面知乎帖子,里面写的很详细了,有疑问的可以跳过去看看;

三,实现你自己的界面逻辑... 是的,没有了

具体代码贴出来,写得有点凌乱, 后续有时间再优化吧...

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<string, string>();

        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<Transform>(true);

            List<Transform> childList = new List<Transform>(_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<string, string>();

            //循环得到物体路径
            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方法里的功能;?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 12:03:55  更:2022-02-26 12:04:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 16:29:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码