问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity UGUI一键绑定UI控件工具开发指南:基于反射特性的优化方案

创作时间:
作者:
@小白创作中心

Unity UGUI一键绑定UI控件工具开发指南:基于反射特性的优化方案

引用
CSDN
1.
https://blog.csdn.net/qq_54351806/article/details/140037013

在Unity开发中,UI控件的绑定是一个常见且繁琐的任务。传统的Transform.Find方法不仅步骤复杂,而且占用空间大,修改起来也不方便。本文将介绍一种基于反射特性的优化方案,通过自定义特性来简化UI控件的绑定过程,实现一键绑定,从而大大加快开发速度。

效果

通过本方案,一行代码即可完成UI控件的绑定。配合后续的生成绑定工具,可以进一步提升开发效率。

实现过程

首先准备面板基类和面板管理类,并创建一个用来测试的面板。

自定义特性

自定义一个特性UIBinderAttribute,用于标记需要被查找的组件。特性中包含一个path字段,用于存储组件的地址。

面板基类中的组件绑定

在面板基类中实现组件绑定逻辑:

var thisType = this.GetType(); // 获取当前面板的类型
var thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); // 获取当前面板的所有字段

Transform trans;
foreach (var field in thisFields)
{
    var atb = field.GetCustomAttribute(typeof(UIBinderAttribute), false) as UIBinderAttribute;
    trans = this.transform.Find(atb.path);
    field.SetValue(this, trans.GetComponent(field.FieldType));
}

优化路径生成

为了进一步优化开发体验,我们开发了一个编辑器工具,可以自动生成绑定代码:

点击工具后,会自动将选中UI组件的绑定代码复制到剪贴板,方便直接粘贴使用。

源代码

以下是完整的源代码实现:

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

public class ABaseUI : MonoBehaviour
{
    public void Init()
    {
        BindingUIComponent();
    }

    private void BindingUIComponent()
    {
        var thisType = this.GetType();
        var thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        UIBinderAttribute atb;
        Transform trans;
        foreach (var field in thisFields)
        {
            atb = field.GetCustomAttribute(typeof(UIBinderAttribute), false) as UIBinderAttribute;
            trans = this.transform.Find(atb.path);
            field.SetValue(this, trans.GetComponent(field.FieldType));
            Debug.Log(field.FieldType);
            Debug.Log(field.GetType());
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using UnityEngine.UI;
using System.Text;
using TMPro;
using UnityEngine.EventSystems;
using Random = System.Random;

public class UIBinderTool : MonoBehaviour
{
    [MenuItem("GameObject/UIBindingTool", false, 1)]
    private static void SingleReplace()
    {
        if (Selection.gameObjects.Length < 1)
            return;
        GameObject selectObj = Selection.gameObjects[0];
        UIBehaviour[] componments = selectObj.GetComponents<UIBehaviour>();
        Type tartgetType = null;
        foreach (var componment in componments)
        {
            if (componments.Length > 1)
            {
                if (componment.GetType() is Image)
                    continue;
            }
            tartgetType = componment.GetType();
        }
        StringBuilder pasteContent = new StringBuilder();
        Transform trans = selectObj.transform;
        string pathContent = string.Empty;
        while (!trans.name.Equals("root"))
        {
            pathContent = trans.parent.name + "/" + pathContent;
            trans = trans.parent;
        }
        pasteContent.Append("\t" + $"[UIBinder(\"{pathContent.ToString()}{selectObj.name}\")]" + "private" + " " + tartgetType.Name + "  a;");
        TextEditor text = new TextEditor();
        text.text = pasteContent.ToString();
        text.SelectAll();
        text.Copy();
        Debug.Log("生成成功");
    }
}

public class UIBinderAttribute : Attribute
{
    public string path;
    public UIBinderAttribute(string path)
    {
        this.path = path;
    }
}

public class UIManager : MonoBehaviour
{
    void Start()
    {
        var canvas = GameObject.Find("Canvas").transform;
        var panel = Resources.Load<GameObject>("LoadingPanel");
        var panelObj = GameObject.Instantiate(panel, canvas);
        panelObj.GetOrAddComponent<LoadingPanel>().Init();
    }
}

本文仅作为流程分享,具体实现细节还需要根据项目实际情况进行修改和完善。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号