Unity UGUI一键绑定UI控件工具(编辑器拓展)

效果

全为一键生成

实现自动生成代码绑定UI控件 并生成字典保存UI控件

减少自己拖拽 和手动书写过程 适用动态加载面板

建议搭配UI框架使用

实现思路

根据当前选中的gameobject 查找其下方是否有对应类型的控件 有就保存到字典中 然后通过向上递归拼凑地址,然后生成到粘贴板 直接粘贴到目标位置即可

实现过程

Selection.gameObjects会获取当前选中的物体数组 我们取出第一个即可

这个字典专门用来存放 我们需要获取的类型和该类型在代码里面的前缀

如 名字叫  AddButton的物体身上的button组件 获取后在代码里面的名字为  btnAddbutton

根据刚才字典的键,就是我们要获取的类型 遍历选中物体下所有子物体是否有该类型的组件 有就存放到字典 改字典的 键是

该控件物体的地址如 

值是控件类型

至于为什么要这样做后面会解释

找到当前foreach循环类型的组件后 会保存到component数组里面 开始拼凑地址 凑地址之前会进行判断 如果后缀 不是自定义的字符串 就不进行生成

这样增加灵活性

然后开始拼凑当前component[i]的地址

(清除后缀  如LoadPlace_Auto会切割为 LoadPlace作为真实名字保存为临时变量 在声明变量时使用)

思路是while循环 当父物体不为选中物体是就一直向上循环拼凑字符串

加入字典的时候为什么要把键 设置为简称加上地址呢

因为如果键是地址的话 如果这个物体上同时拥有 image和text那键就重复了 都是xxx/xxx/xxx

所有改成简称加上地址  这样找到的image在字典中就是  imgxxx/xxx/xxx  不会重复

完成循环后 我们的字典里面已经找到了所有我们需要自动绑定的UI控件

键值对形式为  控件检测+地址,真实控件实例

然后开始生成代码

通过/来分割字符串 获取字符串的最后一位

LoadPlace_auto这个物体的上的image组件 的键就为  imgLeft/CargoShow/LoadPlace_Auto 

我们直接用/切割字符串

获取最后一位 即LoadPlace_Auto 

这样不会出现问题

但如果LoadPlace_Auto 在选中的PlaningPanel下面第一位

键就会变为imgLoadPlace_Auto 这样/切割就会失效 会出bug

所以我们加一个判断 如果切割后只有一位长度 那就要去除前缀

这样才能拿到真实的名字

切割到前面的前缀 获取真实的地址

根据我们的命名规则 拼凑代码中的命名

然后生成到粘贴板即可

代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using UnityEngine.UI;
using System.Text;
using TMPro;

public class UIBindingTool : Editor
{
    private static string endWith = "_Auto";
    /// <summary>
    /// 简称+真实地址  类型
    /// </summary>
    private static Dictionary<string, Type> findDic = new Dictionary<string, Type>();//保存已经找到的控件 类型名字简称+真实地址 类型 原因防止key重复并且都是3位好处理
    private static Dictionary<Type, string> dicMap = GenerateBtuDic();
    [MenuItem("GameObject/GenerateBinding", false, 1)]
    private static void GenerateBinding()
    {

        if (Selection.gameObjects.Length < 1)//返回当前在Hierarchy面板上或Project文件夹下选择的游戏物体GameObject数组,未选择则数组长度则为0
            return;
        GameObject selectObj = Selection.gameObjects[0];//找到选中的第一个物体
                                                        //foreach (var item in Selection.gameObjects)
                                                        //{
                                                        //    Debug.Log(item.name);
                                                        //}
                                                        //if (dicMap == null) ;
                                                        //Dictionary<Type, string> dicMap = GenerateBtuDic();//控件类型对应的名字字典


        StringBuilder pasteContent = new StringBuilder();
        //声明保存的字典 
        //rider不要\t
        // pasteContent.Append("\t#region 自动绑定\n");
        pasteContent.Append("#region 自动绑定\n");
        pasteContent.Append("\tprivate Dictionary<string, UIBehaviour> componentsDic = new Dictionary<string, UIBehaviour>();\n");
        foreach (Type type in dicMap.Keys)//看看物体上有没有对应类型的控件 keys是UI组件类型
        {
            //获取子物体上所有对应UI组件
            Component[] components = selectObj.GetComponentsInChildren(type);//GetComponentsInChildren可以获取到儿子孙子 深度优先 包含自己
            if (components.Length < 1) continue;//没有获取到就下一个
            for (int i = 0; i < components.Length; i++)
            {
                //if (!components[i].name.StartsWith(startsWith))
                if (!components[i].name.EndsWith(endWith))
                    continue;// 加一个字符串条件判断
                //满足条件
                Component component = components[i];

                //组件的名字
                string name = dicMap[type] + component.name.Substring(0, component.name.Length - endWith.Length);
                //组件的地址 
                string path = component.name;
                Transform transform = component.transform;
                //构成控件的path
                while (!transform.parent.name.Equals(selectObj.name))//中间的地址
                {
                    //Debug.Log(transform.name);
                    path = transform.parent.name + "/" + path;
                    transform = transform.parent;
                }
                //地址=父物体名字+中间地址+名字
                //Debug.Log(selectObj.name +"/"+ path);
                findDic.Add(dicMap[type] + /*selectObj.name + "/" +*/ path, type);
                //Debug.Log(dicMap[type] + /*selectObj.name + "/" +*/ path);
                //组件的声明
                pasteContent.Append("\t"+"private" + "\t" + type.Name + "\t" + name + ";");
                pasteContent.Append("\n");

            }
            //Debug.Log(pasteContent);

        }
        pasteContent.Append("\t#endregion\n");
        //查找组件
        pasteContent.Append("\t//自动获取组件添加字典管理");
        pasteContent.Append("\n");
        pasteContent.Append("\tprivate void AutoBindingUI()");
        pasteContent.Append("\n");
        pasteContent.Append("\t{");
        foreach (string item in findDic.Keys)
        {
            //!!!直接在选中物体下面的会有Bug!!!  如果一共就一位 先去掉前缀再继续
            string[] temp = item.Split("/");
            string componentName;
            if (temp.Length > 1)
                //获取真实名字
                componentName = temp[temp.Length - 1];
            else
                componentName = temp[temp.Length - 1].Substring(dicMap[findDic[item]].Length);


            //获取真实地址 Bug
            string realPath = item.Substring(dicMap[findDic[item]].Length);


            //拼接变量名
            string varName = dicMap[findDic[item]] + componentName.Substring(0, componentName.Length - endWith.Length);
            //Debug.Log(componentName.Substring(0, componentName.Length - endWith.Length));
            //Debug.Log(componentName + " " + realPath + " " + varName);
            //语句
            pasteContent.Append("\n");
            pasteContent.Append($"\t\t{varName} = transform.Find(\"{realPath}\").GetComponent<{findDic[item].Name}>();");
            //rigidbody = transform.Find().GetComponent<>();

        }
        //加入字典
        foreach (string item in findDic.Keys)
        {
            //!!!直接在选中物体下面的会有Bug!!!  如果一共就一位 先去掉前缀再继续

            string[] temp = item.Split("/");
            string componentName;
            if (temp.Length > 1)
                //获取真实名字
                componentName = temp[temp.Length - 1];
            else
                componentName = temp[temp.Length - 1].Substring(dicMap[findDic[item]].Length);
            //拼接变量名
            string varName = dicMap[findDic[item]] + componentName.Substring(0, componentName.Length - endWith.Length);
            //Debug.Log(componentName.Substring(0, componentName.Length - endWith.Length));
            //Debug.Log(componentName + " " + realPath + " " + varName);
            //语句
            pasteContent.Append("\n");
            pasteContent.Append($"\t\tcomponentsDic.Add(\"{varName.ToString()}\", {varName});");
            //componentsDic.Add(inputPlaneID.ToString(), inputPlaneID);

        }
        //TODO:生成封装组件事件的方法
        pasteContent.Append("\n");
        pasteContent.Append("\t}");
        TextEditor text = new TextEditor();

        text.text = pasteContent.ToString();
        text.SelectAll();
        text.Copy();
        Debug.Log("生成成功");
    }
    private static Dictionary<Type, string> GenerateBtuDic()//寻找里面有没有我定义的类型的键(key)匹配,然后返回我对应的类型?
    {
        Dictionary<Type, string> dic = new Dictionary<Type, string>();
        dic.Add(typeof(Button), "btn");
        dic.Add(typeof(Scrollbar), "scrB");
        dic.Add(typeof(Image), "img");
        dic.Add(typeof(TMP_InputField), "input");
        dic.Add(typeof(VerticalLayoutGroup), "layoutGRP");
        dic.Add(typeof(Text), "text");
        dic.Add(typeof(TMP_Text), "texT");
        dic.Add(typeof(GridLayoutGroup), "layout");
        dic.Add(typeof(TMP_Dropdown), "dropD");
        return dic;
    }


}

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity UGUI(用户界面)提供了各种控件来创建用户界面。以下是一些常见控件及其事件: 1. Button:Button 控件用于创建一个可点击的按钮。它有以下几个常见的事件: - On Click:当按钮被点击时触发的事件。 - On Pointer Down:当鼠标或手指按下按钮时触发的事件。 - On Pointer Up:当鼠标或手指抬起按钮时触发的事件。 - On Pointer Enter:当鼠标或手指进入按钮区域时触发的事件。 - On Pointer Exit:当鼠标或手指离开按钮区域时触发的事件。 2. Toggle:Toggle 控件用于创建一个可切换状态的开关。它有以下几个常见的事件: - On Value Changed:当 Toggle 的值(选中或未选中)发生改变时触发的事件。 3. Slider:Slider 控件用于创建一个可以拖动的滑块。它有以下几个常见的事件: - On Value Changed:当 Slider 的值发生改变时触发的事件。 4. Scrollbar:Scrollbar 控件用于创建一个可以拖动的滚动条。它有以下几个常见的事件: - On Value Changed:当 Scrollbar 的值发生改变时触发的事件。 5. Dropdown:Dropdown 控件用于创建一个下拉框。它有以下几个常见的事件: - On Value Changed:当 Dropdown 的值(选中的选项)发生改变时触发的事件。 6. InputField:InputField 控件用于创建一个可以输入文本的框。它有以下几个常见的事件: - On Value Changed:当 InputField 的值发生改变时触发的事件。 - On End Edit:当用户完成输入并按下回车键或点击其他地方时触发的事件。 除了以上列出的常见事件之外,每个控件还可能有其他的事件。可以通过在 Inspector 窗口中选择相应的控件并查看其属性面板来了解更多信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值