Unity 编辑器-创建模板脚本,并自动绑定属性,添加点击事件

news2024/11/15 17:58:38

当使用框架开发时,Prefab挂载的很多脚本都有固定的格式。从Unity的基础模板创建cs文件,再修改到应有的模板,会浪费一些时间。尤其是有大量的不同界面时,每个都改一遍,浪费时间不说,还有可能遗漏或错改。写个脚本创建指定的模板代替C#基础模板。

注:当前脚本使用的NGUI,使用UGUI时替换对应的Component即可

代码

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

public class MediatorScriptCreator
{
    private const string MenuItemText1 = "Assets/Create/模板脚本/创建Mediator模板脚本";
    private const string MenuItemText3 = "Assets/Create/模板脚本/添加Mediator模板脚本";
    [MenuItem(MenuItemText1, false, 25)]
    public static void CreateScript()
    {
        CreateScript(false);
    }
   
    
    [MenuItem(MenuItemText3, false, 25)]
    public static void AddScript()
    {
        AddComp();
    }
    
    private static List<GameObject> _nodeList;
    private static List<UISprite> _imgList;
    private static List<UIButton> _btnList;
    private static List<UILabel> _labelList;
    private static List<UISlider> _sliderList;

    private static void CreateScript(bool isPartial)
    {

        var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
        var directoryPath = System.IO.Path.GetDirectoryName(assetPath);
        var folderName = System.IO.Path.GetFileName(directoryPath);
        var folderPath = $"Assets/Game/GameLogic/{folderName}";
        if (!Directory.Exists(folderPath))
        {
            if (directoryPath != null) Directory.CreateDirectory(folderPath);
        }

        var scriptPath = $"{folderPath}/{Selection.activeObject.name}Mediator.cs";
        if (File.Exists(scriptPath))
        {
            Debug.LogError($"The script \"{scriptPath}\" already exists.");
            return;
        }

        var myPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
        // 获取 Prefab 的所有子对象
        GetNodeData(myPrefab);

        var txt = $@"using UnityEngine;
namespace PD
{{
    public {(isPartial ? "partial" : "")} class {Selection.activeObject.name}Mediator : NGuiFormMasterLogic
    {{
        public override string FacadeName
        {{
            get {{ return HomeFacade.Name; }}//TODO:修改FacadeName
        }}

        public new const string NAME = {$"\"{Selection.activeObject.name}Mediator\""};

        public override void OnConstruct(object userData)
        {{
            base.OnConstruct(userData);
            MediatorName = NAME;
        }}
";
        var txtEnd = $@"
    }}
}}";
        for (var i = 0; i < _nodeList.Count; i++)
        {
            var name = _nodeList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private GameObject {name};
";
            txt += str;
        }

        for (var i = 0; i < _imgList.Count; i++)
        {
            var name = _imgList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UISprite {name};
";
            txt += str;
        }

        for (var i = 0; i < _labelList.Count; i++)
        {
            var name = _labelList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UILabel {name};
";
            txt += str;
        }

        for (var i = 0; i < _btnList.Count; i++)
        {
            var name = _btnList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UIButton {name};
";
            txt += str;
        }

        for (var i = 0; i < _sliderList.Count; i++)
        {
            var name = _sliderList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UISlider {name};
";
            txt += str;
        }

        for (var i = 0; i < _btnList.Count; i++)
        {
            var name = _btnList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"


        public void On{name}Click()
        {{
           
        }}

";
            txt += str;
        }


        txt += txtEnd;
        EditorPrefs.SetString("creatorPath", assetPath);
        EditorPrefs.SetString("creatorName", myPrefab.name);
        EditorPrefs.SetString("creatorScriptPath", scriptPath);
        File.WriteAllText(scriptPath, txt);
        AssetDatabase.Refresh();
    }

    public static void AddComp()
    {
        var scriptName = EditorPrefs.GetString("creatorName");
        string[] guids = AssetDatabase.FindAssets(scriptName);

        if (guids.Length > 0)
        {
            var assetPath = EditorPrefs.GetString("creatorPath");
            string path = AssetDatabase.GUIDToAssetPath(guids[0]);
            MonoScript monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
            System.Type type = monoScript.GetClass();
            var prefab =
                GameObject.Instantiate(
                    AssetDatabase
                        .LoadMainAssetAtPath(
                            assetPath)) as GameObject; // PrefabUtility.LoadPrefabContents(assetPath);//
            var component = prefab.AddComponent(type);
            // 获取所有字段
            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            var list = prefab.GetComponentsInChildren<Transform>(true).Where(a => a.name.StartsWith("m_")).ToList();

            foreach (FieldInfo field in fields)
            {
                // 判断字段是否被序列化
                var attributes = field.GetCustomAttributes(typeof(SerializeField), false);
                if (attributes.Length > 0)
                {
                    var temp = field.Name + "";
                    var name = temp[..1].ToLower() + temp[1..];
                    var go = list.FirstOrDefault(a => a.name == $"m_{name}");
                    if (go != null)
                    {
                        list.Remove(go);
                        var btn = go.GetComponent<UIButton>();
                        var slider = go.GetComponent<UISlider>();
                        var img = go.GetComponent<UISprite>();
                        var txt = go.GetComponent<UILabel>();
                        if (btn != null)
                        {
                            var str = $"On{field.Name}Click";
                            Debug.Log(str);
                            var delegateFunc1 = new EventDelegate(component as MonoBehaviour, str);
                            btn.onClick.Add(delegateFunc1);
                            field.SetValue(component, btn);
                        }
                        else if (slider != null)
                        {
                            field.SetValue(component, slider);
                        }
                        else if (img != null)
                        {
                            field.SetValue(component, img);
                        }
                        else if (txt != null)
                        {
                            field.SetValue(component, txt);
                        }
                        else
                        {
                            field.SetValue(component, go.gameObject);
                        }
                    }
                }
            }

            // GetNodeData(prefab);
            // PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, assetPath);
            PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, assetPath, InteractionMode.AutomatedAction);
            Object.DestroyImmediate(prefab);
            AssetDatabase.Refresh();
        }
        else
        {
            Debug.LogError($"请先生成脚本");
        }
    }
    [MenuItem(MenuItemText1, true)]
    public static bool CreatorNormal()
    {
        if (!Selection.activeObject) return false;
        var prefabAssetType = PrefabUtility.GetPrefabAssetType(Selection.activeObject);
        return prefabAssetType != PrefabAssetType.NotAPrefab;

    }
    
    [MenuItem(MenuItemText3, true)]
    public static bool AddScript1()
    {
        if (!Selection.activeObject) return false;
        var prefabAssetType = PrefabUtility.GetPrefabAssetType(Selection.activeObject);
        return prefabAssetType != PrefabAssetType.NotAPrefab;

    }
    private static void GetNodeData(GameObject prefab)
    {
        Transform[] nodes = prefab.GetComponentsInChildren<Transform>(true);
        _nodeList = new List<GameObject>();
        _imgList = new List<UISprite>();
        _labelList = new List<UILabel>();
        _btnList = new List<UIButton>();
        _sliderList = new List<UISlider>();                                                                                              
        // 遍历所有子对象
        foreach (var node in nodes)
        {
            if (!node.gameObject.name.StartsWith("m_")) continue;
            var btn = node.GetComponent<UIButton>();
            var img = node.GetComponent<UISprite>();
            var label = node.GetComponent<UILabel>();
            var slider = node.GetComponent<UISlider>();
            if (btn != null)
            {
                _btnList.Add(btn);
            }
            else if (slider != null)
            {
                _sliderList.Add(slider);
            }
            else if (img != null)
            {
                _imgList.Add(img);
            }
            else if (label != null)
            {
                _labelList.Add(label);
            }
            else
            {
                _nodeList.Add(node.gameObject);
            }
        }
    }
}



使用方法

知识点

1.字符串使用@前缀,可以不使用\n换行。和$搭配使用时,字符串中如果有 { 需要用 {{ 两个大括号表示,第一个为转义。 字符串中有 ” 时,需要使用反斜杠 " 转义
2.判断物体是不是Prefab,PrefabUtility.GetPrefabAssetType(Selection.activeObject) != PrefabAssetType.NotAPrefab;
3.[MenuItem(MenuItemText2, true)] 第二个参数 bool值表示是否显示本扩展方法
4.获取指定脚本所有的Pulbic[SerializeField]的属性: type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

查询直播频道发起的签到记录

接口描述 1、通过直播场次id&#xff0c;查询签到发起记录 2、接口支持https协议 接口URL http://api.polyv.net/live/v3/channel/chat/checkin-by-sessionId 请求方式 GET 请求参数描述 参数名必选类型说明appIdtrueString账号appIdtimestamptrueLong当前13位毫秒级时间戳&…

OSPF实验2

OSPF实验2 要求&#xff1a; 1.如图连接&#xff0c;合理规划IP地址&#xff0c;所有路由器各自创建一个loopback接口 2.R1再创建三个接口IP地址为201.1.1.1/24、201.1.2.1/24、201.1.3.1/24 R5再创建三个接口IP地址为202.1.1.1/24、202.1.2.1/24、202.1.3.1/24 R7再创建三…

小红书如何开店,送你一份保姆级开店教程

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 今天&#xff0c;我们来谈谈小红书的电子商务。这也是今年非常流行的电子商务平台。很多人说…

《设计模式》责任链模式

《设计模式》责任链模式 定义&#xff1a; 责任链模式将链中每一个节点都看成一个对象&#xff0c;并且将这些节点对象连成一条链&#xff0c;请求会沿着这条链进行传递&#xff0c;直到有对象处理它为止&#xff0c;这使得多个对象都有机会接收请求&#xff0c;避免了请求发送…

warp框架教程3-path, method和自定义请求方法

path, method和自定义请求方法 path 是 warp 中的路由系统, 一个 web 框架的灵魂所在, 一个优美的路由系统可以给我们带来非常良好的使用体验, 而 warp 的路由体验本身就是非常 nice 的。在本文中将展示一个 RESTful 风格的 API 设计。下面先来学习一下 path 模块。 path 模块…

从小白到大神之路之学习运维第56天--------shell脚本实例应用2.0之有趣的知识

第三阶段基础 时 间&#xff1a;2023年7月10日 参加人&#xff1a;全班人员 内 容&#xff1a; shell实例 目录 shell脚本应用&#xff1a; 一、if判断 1、if判断的类型 1&#xff09;单分支 2&#xff09;双分支 3&#xff09;多分支 2、单分支if判断 1&#x…

Could not increase number of max_open_files to more than 5000 (request: 65535)

修改MySQL 打开文件数量限制 修改内核限制 ulimit -n //查看系统限制 修改 /etc/security/limits.conf 添加 soft nofile 65530hard nofile 65535 mysql> SHOW VARIABLES LIKE open_files_limit; 通过 MySQL 命令行检查新限制。您可以使用以下查询&#xff0c;确保设置了新…

vue3使用less入门使用案例(webStrom)

文章目录 简介安装less基础代码效果 less进阶代码效果 简介 less&#xff1a;css预处理语言 安装 npm i less3.0.4 -Dless打包解释器 npm i less-loader5.0.0 -Dless基础代码 <template><div class"a"></div> </template><style lang…

Java Web Servlet (1)23.7.7

Servlet 1&#xff0c; Servlet 1.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现&#xff0c;根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&a…

【日常记录】CentOS7.5 安装tomcat放行8080端口后无法访问

环境 操作系统版本信息&#xff1a; [rootlocalhost conf]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core)JAVA版本信息 [rootlocalhost conf]# java -version openjdk version "1.8.0_372" OpenJDK Runtime Environment (build 1.8.0_372-b07) …

闲人闲谈PS之四十四——供应链透明化

惯例闲话&#xff1a; 近期工作和天气一样&#xff0c;如火如荼&#xff0c;前面1个月&#xff0c;拼全力搞了一个新功能&#xff0c;把闲人折腾的够呛&#xff0c;现在回头看看这个过程&#xff0c;倒也回味无穷&#xff0c;如何利用信息化工具&#xff0c;搞点数字化的活&am…

ORA-39168: Object path STATISTICS was not found

上周某客户因异常断电导致lun&#xff0c;某个测试环境无法启动&#xff0c;客户只提供了一个1周前.dmp文件&#xff0c;需要在新环境中导入恢复&#xff0c;解决表空间和临时表空间问题后&#xff0c;导入报错如下 Import: Release 11.2.0.4.0 - Production on Thu Jul 6 07:…

基础篇--Cortex-M系列介绍

视频教程 体系结构&#xff08;ARM架构版本&#xff09;与其对应的ARM处理器内核 Cortex-M系列介绍 ARM公司 ARM公司&#xff1a;只做内核设计和IP授权&#xff0c;不参与芯片设计 ARM架构为什么能风靡全球&#xff1f; Cortex内核分类及特征 Cortex-M3/4/7介绍

几个有趣的Python库,建议收藏~

随着每个 Python 版本的发布&#xff0c;都会添加新模块&#xff0c;并引入新的更好的做事方式&#xff0c;虽然我们都习惯了使用好的旧 Python 库和某些做事方式&#xff0c;但现在也时候升级并利用新的和改进的模块及其特性了。 Pathlib pathlib 绝对是 Python 标准库中最近…

python 第十二章 面向对象

系列文章目录 第一章 初识python 第二章 变量 第三章 基础语句 第四章 字符串str 第五章 列表list [] 第六章 元组tuple ( ) 第七章 字典dict {} 第八章 集合set {} 第九章 常用操作 第十章 函数 第十一章 文件操作 文章目录 系列文章目录12.1面向对象实现方法定义类经典类&am…

《Redis 核心技术与实战》课程学习笔记(五)

数据同步&#xff1a;主从库如何实现数据一致&#xff1f; 那我们总说的 Redis 具有高可靠性&#xff0c;又是什么意思呢&#xff1f; 其实&#xff0c;这里有两层含义&#xff1a;一是数据尽量少丢失&#xff0c;二是服务尽量少中断。AOF 和 RDB 保证了前者&#xff0c;而对于…

【NLP,Huggingface,Colab】使用 Trainer 训练模型,并保存模型参数

【NLP&#xff0c;Huggingface&#xff0c;Colab】使用 Trainer 训练模型&#xff0c;并保存模型参数 前置知识上代码 前置知识 Colab 的使用Huggingface 官网和一些基础API 上代码 首先&#xff0c;建议保存代码到 VSCode&#xff0c;这样双击关键类&#xff0c;F12可以进入…

一个HTTP的流程

1&#xff0c;键入一个URL后浏览器将URL进行解析 2,浏览器解析URL后&#xff0c;需要查询服务器域名对应的IP地址。 流程如下&#xff1a;查询缓存&#xff0d; >客户端发送DNS请求-> 根DNS&#xff0c;根DNS根据 .COM-> 顶级域名服务器&#xff0c;根据baidu->权…

【Linux后端服务器开发】管道设计

目录 一、管道通信 二、匿名管道 1. 匿名管道通信 2. 匿名管道设计 三、命名管道 comm.hpp client.cc serve.cc 一、管道通信 进程通信 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源 通知事件&…

Matlab建模实战学习——(规划问题)

1.Matlab函数linprog&#xff08;&#xff09;的使用 1.1 Matlab基本描述 1.2 函数linprog&#xff08;&#xff09; 三种表达形式 [x,fval] linprog(c,A,b)[x,fval] linprog(c,A,b,Acq,bcq)[x,fval]linprog(c,A,b,Aeq,beq,lb,ub) 其中 x返回的是决策向量的取值&#xf…