Unity编辑器扩展——自动生成UI界面脚本

这篇具有很好参考价值的文章主要介绍了Unity编辑器扩展——自动生成UI界面脚本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一:前言

对于面板赋值或Find绑定UI组件,我们可以使用一种工具化的方式去自动生成代码并绑定对象,增加效率
分为logic和view,view层是UI界面上的组件,每次都会自动生成并覆盖,logic层是逻辑


二:使用

Unity编辑器扩展——自动生成UI界面脚本
例如一个UI界面,我们只需要做成预制体并在Project下右键预制体,选择AutoGen/Create View则会自动生成view和logic两个脚本,logic是我们要编写逻辑的脚本,view是每次都会自动生成并覆盖的脚本


三:说明

——以下几个路径都是可以自定义的(view和logic生成的路径、view和logic模版文件的路径)
Unity编辑器扩展——自动生成UI界面脚本


——可以自定义忽略的组件类型列表
Unity编辑器扩展——自动生成UI界面脚本


——只会生成对象名带下划线的
Unity编辑器扩展——自动生成UI界面脚本文章来源地址https://www.toymoban.com/news/detail-509736.html


四:代码实现 

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
using System;

public class AutoGenCode
{
    //logic层代码路径
    const string LogicDir = "Assets/AutoGen/Logic";
    //view层代码路径
    const string ViewDir = "Assets/AutoGen/View";
    //logic层模版文件路径
    const string LogicTempletePath = "Assets/AutoGen/LogicTemplete.txt";
    //view层模版文件路径
    const string ViewTempletePath = "Assets/AutoGen/ViewTemplete.txt";

    //命名空间模板
    const string NameSpaceTemplete = "using {0};";
    //字段模板
    const string FieldTemplete = "public {0} {1};\t";
    //方法模板
    const string MethodTemplete = "{0} = gameObject.transform.Find(\"{1}\").GetComponent<{2}>();\t\t";

    /// <summary>
    /// 忽略的组件类型列表
    /// </summary>
    static List<Type> IgnoreComponentTypeList = new List<Type>()
    {
        typeof(CanvasRenderer),
        typeof(RectTransform),
    };

    [MenuItem("Assets/AutoGen/Create View", priority = 0)]
    static void CreateLogicAndView()
    {
        GameObject go = Selection.activeGameObject;
        //判断是否是prefab
        if (PrefabUtility.GetPrefabAssetType(go) != PrefabAssetType.Regular)
        {
            Debug.LogWarning("选择的不是预制体,选择的对象:" + go.name);
            return;
        }
        if (!Directory.Exists(ViewDir))
        {
            Directory.CreateDirectory(ViewDir);
        }
        if (!Directory.Exists(LogicDir))
        {
            Directory.CreateDirectory(LogicDir);
        }

        string className = go.name + "View";
        StringBuilder fieldContent = new StringBuilder();
        StringBuilder methodContent = new StringBuilder();
        StringBuilder nameSpaceContent = new StringBuilder();
        nameSpaceContent.AppendLine(NameSpaceTemplete.Replace("{0}", "UnityEngine"));//必须有UnityEngine命名空间

        string logicTempleteContent = File.ReadAllText(LogicTempletePath, Encoding.UTF8);
        string viewTempleteContent = File.ReadAllText(ViewTempletePath, Encoding.UTF8);
        string logicPath = LogicDir + "/" + go.name + "Logic.cs";
        string viewPath = ViewDir + "/" + go.name + "View.cs";

        List<string> tempNameSpaceList = new List<string>();

        //计算所有子物体组件数据
        List<ComponentInfo> infoList = new List<ComponentInfo>();
        CalcComponentInfo("", go.transform, infoList);
        foreach (var tempInfo in infoList)
        {
            //字段
            string tempFieldStr = FieldTemplete.Replace("{0}", tempInfo.TypeStr);
            tempFieldStr = tempFieldStr.Replace("{1}", tempInfo.FieldName);
            fieldContent.AppendLine(tempFieldStr);

            //绑定方法
            string tempMethodStr = MethodTemplete.Replace("{0}", tempInfo.FieldName);
            tempMethodStr = tempMethodStr.Replace("{1}", tempInfo.Path);
            tempMethodStr = tempMethodStr.Replace("{2}", tempInfo.TypeStr);
            methodContent.AppendLine(tempMethodStr);

            //命名空间
            if (!tempNameSpaceList.Contains(tempInfo.NameSpace))
            {
                string tempNameSpaceStr = NameSpaceTemplete.Replace("{0}", tempInfo.NameSpace);
                tempNameSpaceList.Add(tempInfo.NameSpace);
                nameSpaceContent.AppendLine(tempNameSpaceStr);
            }
        }

        //logic层脚本
        if (!File.Exists(logicPath))
        {
            using (StreamWriter sw = new StreamWriter(logicPath))
            {
                string content = logicTempleteContent;
                content = content.Replace("#CLASSNAME#", className);
                sw.Write(content);
                sw.Close();
            }
        }
        //view层脚本
        using (StreamWriter sw = new StreamWriter(viewPath))
        {
            string content = viewTempleteContent;
            content = content.Replace("#NAMESPACE#", nameSpaceContent.ToString());
            content = content.Replace("#CLASSNAME#", className);
            content = content.Replace("#FIELD_BIND#", fieldContent.ToString());
            content = content.Replace("#METHOD_BIND#", methodContent.ToString());
            sw.Write(content);
            sw.Close();
        }

        AssetDatabase.Refresh();
    }

    /// <summary>
    /// 计算所有子物体组件数据
    /// </summary>
    static void CalcComponentInfo(string path, Transform child, List<ComponentInfo> infoList)
    {
        bool isRoot = string.IsNullOrEmpty(path);
        if (!isRoot
            && IsVaildField(child.name))
        {
            var componentList = child.GetComponents<Component>();
            foreach (var tempComponent in componentList)
            {
                ComponentInfo info = new ComponentInfo()
                {
                    Path = path,
                    go = child.gameObject,
                    NameSpace = tempComponent.GetType().Namespace,
                    TypeStr = tempComponent.GetType().Name,
                };
                if (!HaveSameComponentInfo(info, infoList)
                    && !IgnoreComponentTypeList.Contains(tempComponent.GetType()))
                {
                    infoList.Add(info);
                }
            }
        }

        foreach (Transform tempTrans in child.transform)
        {
            CalcComponentInfo(isRoot ? tempTrans.name : path + "/" + tempTrans.name, tempTrans.transform, infoList);
        }
    }

    /// <summary>
    /// 是否为合法的字段名
    /// </summary>
    static bool IsVaildField(string goName)
    {
        if (goName.Contains("_"))
        {
            if (int.TryParse(goName[0].ToString(), out _))
            {
                Debug.LogWarning("字段名不能以数字开头:, goName :" + goName);
                return false;
            }
            return true;
        }
        return false;
    }

    /// <summary>
    /// 是否有相同的组件数据
    /// </summary>
    static bool HaveSameComponentInfo(ComponentInfo info, List<ComponentInfo> infoList)
    {
        foreach (var tempInfo in infoList)
        {
            if (tempInfo.FieldName == info.FieldName)
            {
                Debug.LogWarning("子物体名重复:, goName :" + info.go.name);
                return true;
            }
        }
        return false;
    }
}

/// <summary>
/// 组件数据
/// </summary>
public class ComponentInfo
{
    public string Path;
    public GameObject go;
    public string NameSpace;
    public string TypeStr;
    public string FieldName
    {
        get
        {
            return $"{go.name}_{TypeStr}";
        }
    }
}

到了这里,关于Unity编辑器扩展——自动生成UI界面脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity编辑器扩展】 | 编辑器扩展入门基础

    前言 当谈到游戏开发工具,Unity编辑器是一个备受赞誉的平台。它为开发者提供了一个强大且灵活的环境,使他们能够创建令人惊叹的游戏和交互式体验。 然而,Unity编辑器本身也是可以扩展和定制的,这为开发者提供了进一步提升工作流程和增强功能的机会。 在Unity 编辑器

    2024年02月10日
    浏览(84)
  • Unity 可视化节点编辑器(GraphView、编辑器扩展)

      前几天把导师的项目打包发布交了一稿,这半个星期除了再把项目缝缝补补外(说实话项目做到后边实在有些无聊,都是些琐碎的东西而且自己也学不到什么,纯粹是 浪费 消磨时间)无聊逛Unity商店发现了个有意思的东西,说实话一开始我以为只是单纯绘制的2D动画:

    2024年02月12日
    浏览(63)
  • Unity编辑器扩展(外挂)

    每日一句:未来的样子藏在现在的努力里 目录 什么是编译器开发 C#特性[System.Serializable] 特殊目录 命名空间 /*检视器属性控制*/     //添加变量悬浮提示文字     //给数值设定范围(最小0,最大150) //指定输入框,拥有5行 //默认显示5行,最多显示10行内容,再多用滚动条控

    2024年01月24日
    浏览(88)
  • Unity编辑器扩展之GenericMenu菜单扩展

    内容将会持续更新,有错误的地方欢迎指正,谢谢!   Unity编辑器扩展之GenericMenu自定义菜单       TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 TechX —— 心探索、心进取! 助力快速掌握 GenericMenu 菜单扩展 为初学者节省宝贵的

    2024年02月01日
    浏览(76)
  • Unity 扩展自定义编辑器窗口

    在Assets文件夹路径下任意位置创建Editor文件夹,将扩展编辑器的代码放在Editor文件夹下 代码中首先引用命名空间 然后将创建的类继承自EditorWindow 然后通过扩展编辑器菜单功能调用创建窗口的方法 要注意方法中泛型参数需要传入的是自己代码的类,这个功能是根据后面OnGUI方

    2024年04月27日
    浏览(57)
  • Unity 编辑器扩展之 Attribute

    Unity内置属性[Attribute]是一种类似修饰功能的标签。可以对OnSceneGUI,InspectorGUI,MenuGUI,WindowGUI等实现各种各样的GUI扩展。用户只要添加上特性标签,就能够自由的使用这些扩展功能。下面列出一些常用的标签: 隐藏属性在Inspector面板上的显示。在继承了MonoBehaviour的类中,用

    2023年04月09日
    浏览(71)
  • Unity编辑扩展:功能篇之Json数据编辑器

    前言 编辑器扩展算是比较纯粹的功能开发,基本没有什么理论知识,都是一些 Unity 相关接口的使用与数据类型的设计操作等。在本篇文章主要的文字描述基本都是在做代码解释,为了使内容接受度更高,我会尽量描述到代码结构中的每个细节。如果有对此不太了解又很感兴

    2024年02月06日
    浏览(103)
  • 【Unity编辑器扩展】| Inspector监视器面板扩展

    前言 前面我们介绍了Unity中编辑器扩展的一些基本概念及基础知识,还有编辑器扩展中用到的相关特性Attribute介绍。 后面就来针对Uniity编辑器扩展中比较常用的模块进行学习介绍。 本文就来详细介绍一下Unity编辑器扩展中关于 Inspector面板 扩展功能学习。

    2024年02月08日
    浏览(66)
  • 盘点Unity几款编辑器扩展工具

    unity 编辑器一个不容忽视的强大之处就是非常易于自定义扩展工具,来满足各种各样的美术、策划及程序上的需求。今天为大家介绍Asset Store资源商店中几款实用的编辑器扩展工具,帮助大家直接在Unity编辑器中完成3D建模与调整工作,免去与其它软件进行数据转换的过程,从

    2024年04月09日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包