Unity通过Attribute代替getComponent获取组件
程序员文章站
2022-06-15 14:21:43
...
每次用Unity做了一个界面,写代码时都要为了获取UI的组件或者子物体而写一堆的
Transform.FindChild 和 getComponent 这么做虽然没什么错,但是写出来的代码
太难看了,冗余代码也多,实在受不了了,所以写了一个工具类,通过C#的Attribute
特性来获取组件和子物体
先看效果
这里有一个物体,包含a,b,c 三个子物体
c物体上挂有SpriteRenderer组建
想在我们给GameObject添加一个测试脚本Test
正常情况下我们会这么做:
现在我们不这么写了:
下面是运行结果:
可以看到c和SpriteRenderer都拿到了
如果我们想自动为c附加个Button组件
可以直接这样:
运行后我们就可以看到Button了
很简单省事吧。
下面是代码
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);
}
}
}
}
}