欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity通过Attribute代替getComponent获取组件

程序员文章站 2022-06-15 14:21:43
...

每次用Unity做了一个界面,写代码时都要为了获取UI的组件或者子物体而写一堆的
Transform.FindChild 和 getComponent 这么做虽然没什么错,但是写出来的代码
太难看了,冗余代码也多,实在受不了了,所以写了一个工具类,通过C#的Attribute
特性来获取组件和子物体

先看效果
Unity通过Attribute代替getComponent获取组件
这里有一个物体,包含a,b,c 三个子物体
Unity通过Attribute代替getComponent获取组件
c物体上挂有SpriteRenderer组建

想在我们给GameObject添加一个测试脚本Test
正常情况下我们会这么做:
Unity通过Attribute代替getComponent获取组件

现在我们不这么写了:
Unity通过Attribute代替getComponent获取组件
下面是运行结果:
Unity通过Attribute代替getComponent获取组件

可以看到c和SpriteRenderer都拿到了
如果我们想自动为c附加个Button组件
可以直接这样:
Unity通过Attribute代替getComponent获取组件

运行后我们就可以看到Button了
Unity通过Attribute代替getComponent获取组件
很简单省事吧。
下面是代码


PathAttr.cs

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

[AttributeUsage(AttributeTargets.Field)]
public class PathAttr : Attribute {

    public string path = "";
    public int type = 1;
    public PathAttr(string path){
        this.path = path;
    }

    public PathAttr(string path, int type){
        this.path = path;
        this.type = type;
    }
}

PathMono.cs

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

public class PathMono : MonoBehaviour
{
    private void InitAdd(string path, FieldInfo fi)
    {
        Type type = fi.FieldType;
        string[] pathes = path.Split('/');
        Transform nowPos = transform;

        if (!string.IsNullOrEmpty(path))
        {
            for (int i = 0; i < pathes.Length; i++)
            {
                string nodeName = pathes[i];
                Transform trans = nowPos.FindChild(nodeName);
                if (trans == null)
                {
                    GameObject newGO = new GameObject(nodeName);
                    newGO.transform.SetParent(nowPos);
                    nowPos = newGO.transform;
                    continue;
                }
                else
                {
                    nowPos = trans;
                    continue;
                }
            }
        }
        if (type.IsSubclassOf(typeof(Component)))
        {
            Component c = nowPos.GetComponent(type);
            if (c == null)
                c = nowPos.gameObject.AddComponent(type);
            fi.SetValue(this, c);
        }
        else if (type == typeof(GameObject))
        {
            fi.SetValue(this, nowPos.gameObject);
        }
    }

    public void Init()
    {
        BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        FieldInfo[] fi = this.GetType().GetFields(flag);
        for (int i = 0; i < fi.Length; i++)
        {
            FieldInfo f = fi[i];
            PathAttr mn = Attribute.GetCustomAttribute(f, typeof(PathAttr)) as PathAttr;
            if (mn == null) continue;
            if (mn.type == 2)
            {
                InitAdd(mn.path, f);
                continue;
            }
            string path = mn.path;
            Transform trs = null;
            if (string.IsNullOrEmpty(path))
            {
                trs = transform;
            }
            else
            {
                trs = transform.FindChild(path);
            }

            if (trs == null)
            {
                if (mn.type == 1)
                {
                    continue;
                }
                else if (mn.type == 3)
                {
                    InitAdd(path, f);
                }
            }
            else
            {

                if (f.FieldType.IsSubclassOf(typeof(Component)))
                {
                    Component c = trs.GetComponent(f.FieldType);
                    if(c == null && mn.type == 3){
                        c = trs.gameObject.AddComponent(f.FieldType);
                    }
                    f.SetValue(this, c);
                }
                else if (f.FieldType == typeof(GameObject))
                {
                    f.SetValue(this, trs.gameObject);
                }
                else if (f.FieldType == typeof(Transform))
                {
                    f.SetValue(this, trs);
                }
            }
        }
    }
}
相关标签: unity ui 界面