【Unity编辑器扩展】一键生成UI相关代码和赋值

0. 前言

如果预制体按照既定规则,画完之后,能不能一键生成需要的引用,然后自动拖拽变量,我们只需要关注和书写,按钮的点击事件,Slider 的滑动事件这样,而不用再去找组件,拖UI,节省一些开发精力和时间呢,虽然可能不多,但是好用呀

1. 视频链接

不是笔者,不是引流,b站的一个宝藏up讲的,学之,改进,有感,所记
Unity游戏UI开发神器,一键实现ui组件绑定,绝对干货

2. 预制体结构

在这里插入图片描述

3. 导出工具代码

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

public class ExportUIScript : EditorWindow
{
    private static string exportString = "";
    private static Dictionary<string, string> uiTypeDic = new Dictionary<string, string>()
    {
        // 只读取以下标签的节点,不是以下标签的节点忽略自己但是会读取子节点,以_开头的忽略自己和子节点
        {"Btn","Button"},   // btn_按钮名
        {"Img","Image"},
        {"GameObj","GameObject"},
        {"Text","Text"},
        {"Input","InputField"},
        {"Slider","Slider"},
        {"Scroll","ScrollRect"},
        {"UI","View"}, // 类型为脚本,命名格式为 ui_脚本名
    };

    [MenuItem("Tools/快捷导出UI组件 #&%Q")]
    private static void ShowWindow() 
    {
        GetWindow(typeof(ExportUIScript));
    }

    private void OnGUI()
    {
        GUIStyle style = new GUIStyle();
        style.normal.textColor = Color.red;
        style.fontSize = 18;
        GUIStyle style1 = new GUIStyle();
        style1.normal.textColor = Color.white;
        style1.fontSize = 15;

        EditorGUILayout.LabelField("注意:命名规则", style);
        EditorGUILayout.Space(20);
        EditorGUILayout.LabelField("例 : Btn_你的命名", style);
        EditorGUILayout.LabelField("Btn,	Button", style1);
        EditorGUILayout.LabelField("Img,	Image", style1);
        EditorGUILayout.LabelField("GameObj,GameObject", style1);
        EditorGUILayout.LabelField("Text,	Text", style1);
        EditorGUILayout.LabelField("Input,	InputField", style1);
        EditorGUILayout.LabelField("Slider,	Slider", style1);
        EditorGUILayout.LabelField("Scroll,	ScrollRect", style1);
        EditorGUILayout.LabelField("UI,		View", style1);
        EditorGUILayout.LabelField("类型为脚本,命名格式为 UI_脚本名", style);
        EditorGUILayout.Space(20);

        EditorGUILayout.LabelField("1. 需要先双击进入预制体", style);
        EditorGUILayout.LabelField("2. 选择想生成代码的节点", style);
        EditorGUILayout.LabelField("3. 如果不选择节点, 即按规则全生成", style);
        EditorGUILayout.Space(20);

        if (GUILayout.Button("导出脚本代码"))
        {
            ExportUIComp();
        }
    }
    private static void ExportUIComp()
    {
        var prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
        if (prefabStage == null)
        {
            Debug.LogError("当前没有编辑预设, 请双击进入预制体, 再使用工具!");
            return;
        }
        exportString = "";

        GameObject basePrebabModal = AssetDatabase.LoadAssetAtPath(prefabStage.assetPath, typeof(GameObject)) as GameObject;

        exportString += "\n#region ui component\n";

        ExportUICompList(basePrebabModal.transform, "");

        exportString += "\nprivate void Reset()\n" +
                        "{\n";
        ExportResetFunc(basePrebabModal.transform, "");

        exportString += "}\n";

        exportString += "\n#endregion\n";

        GUIUtility.systemCopyBuffer = exportString;
        Debug.Log(exportString);
        Debug.Log("已保存到剪贴板");
    }


    /// <summary>
    /// 导出ui组件列表文本,ui命名规范为 "{uiTypeDic中的前缀}_{任意名字}"
    /// </summary>
    private static void ExportUICompList(Transform transform, string path = "")
    {
        var len = transform.childCount;
        for (var i = 0; i < len; i++)
        {
            var childTrans = transform.GetChild(i);
            var name = childTrans.name;
            var uiTypeArr = name.Split('_');
            string uiType = uiTypeArr[0];
            bool forChild = true;       // 是否递归子节点
            bool ignore = false;      // 是否忽略当前节点
            string typeName = "";
            if (!uiTypeDic.TryGetValue(uiType, out typeName))
            {
                ignore = true;
                // Debug.LogWarning("未知的ui类型:" + uiType);
            }
            // 需要特殊处理的类型
            switch (uiType)
            {
                case "UI":
                    typeName = uiTypeArr[1];
                    forChild = false;
                    break;
                case "Scroll":
                    forChild = false;
                    break;
                case "":        // _name 
                    ignore = true;
                    forChild = false;
                    break;
            }

            if (!ignore)
            {
                string targetStr = $"[SerializeField] private {typeName} {name};\n";
                if (exportString.IndexOf(targetStr) == -1)
                {
                    exportString += targetStr;
                }
                else
                {
                    Debug.LogError($"重复的属性名={name} path={path}");
                }

            }
            if (forChild)
            {
                ExportUICompList(childTrans, path + "/" + name);
            }

        }
    }

    private static void ExportResetFunc(Transform a_trans, string a_path)
    {
        var len = a_trans.childCount;
        for (var i = 0; i < len; i++)
        {
            var childTrans = a_trans.GetChild(i);
            var name = childTrans.name;
            var uiTypeArr = name.Split('_');
            string uiType = uiTypeArr[0];
            bool forChild = true;
            bool ignore = false;
            string typeName = "";
            if (!uiTypeDic.TryGetValue(uiType, out typeName))
            {
                ignore = true;
                // Debug.LogWarning("未知的ui类型:" + uiType);
            }
            switch (uiType)
            {
                case "UI":
                    typeName = uiTypeArr[1];
                    forChild = false;
                    break;
                case "Scroll":
                    forChild = false;
                    break;
                case "": // 跳过
                    ignore = true;
                    forChild = false;
                    break;
            }

            if (!ignore)
            {
                string targetStr;

                if (a_path == "")
                {
                    if (uiType == "GameObj")
                    {
                        targetStr = $"{name} = transform.Find(\"{name}\").gameObject;\n";
                    }
                    else
                    {
                        targetStr = $"{name} = transform.Find(\"{name}\").GetComponent<{typeName}>();\n";
                    }
                }
                else
                {
                    if (uiType == "GameObj")
                    {
                        targetStr = $"{name} = transform.Find(\"{a_path}/{name}\").gameObject;\n";
                    }
                    else
                    {
                        targetStr = $"{name} = transform.Find(\"{a_path}/{name}\").GetComponent<{typeName}>();\n";
                    }
                }

                if (exportString.IndexOf(targetStr) == -1)
                {
                    exportString += targetStr;
                }
                else
                {
                    Debug.LogError($"重复的属性名={name} path={a_path}");
                }
            }
            if (forChild)
            {
                if (a_path == "")
                {
                    ExportResetFunc(childTrans, name);
                }
                else
                {
                    ExportResetFunc(childTrans, a_path + "/" + name);
                }
            }
        }
    }
}

4. 工具截图

在这里插入图片描述

5. 生成的UI代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UITask : MonoBehaviour
{
    #region ui component
    [SerializeField] private Button Btn_Close;
    [SerializeField] private Text Text_Title;
    [SerializeField] private Slider Slider_Progress;
    [SerializeField] private Button Btn_Award1;
    [SerializeField] private Button Btn_Award2;
    [SerializeField] private Button Btn_Award3;

    private void Reset()
    {
        Btn_Close = transform.Find("Btn_Close").GetComponent<Button>();
        Text_Title = transform.Find("Text_Title").GetComponent<Text>();
        Slider_Progress = transform.Find("Slider_Progress").GetComponent<Slider>();
        Btn_Award1 = transform.Find("Slider_Progress/Btn_Award1").GetComponent<Button>();
        Btn_Award2 = transform.Find("Slider_Progress/Btn_Award2").GetComponent<Button>();
        Btn_Award3 = transform.Find("Slider_Progress/Btn_Award3").GetComponent<Button>();
    }
    #endregion
}

6. 实操

6.1 Reset前

在这里插入图片描述

6.2 Reset后

在这里插入图片描述
在这里插入图片描述

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值