Files
aibis-dream/Assets/Scripts/Framework/Core/UnityTool.cs
T
2025-11-19 15:08:08 +08:00

144 lines
4.7 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
namespace AibisDream.Framework
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class FindComponentAttribute : Attribute
{
public readonly string goName;
public readonly bool getChild;
/// <summary>
/// 查找游戏物体组件的特性
/// </summary>
/// <param name="goName">游戏物体名字</param>
/// <param name="getChild">
/// true => 查找对应名字对象的下一级子物体 通常名字为父物体名字 类型为子物体
/// false => 查找对应名字的对象 通常会将类型和名字对应</param>
public FindComponentAttribute(string goName = null, bool getChild = false)
{
this.goName = goName;
this.getChild = getChild;
}
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class FindComponentsInChildrenAttribute : Attribute
{
/// 空类
/// 直接获取下层所有组件
}
public static class UnityTool
{
/// <summary>
/// 查找所有带标记的组件
/// 与FindComponent特性配合使用
/// </summary>
public static void FindComponents(this Component mono)
{
Dictionary<Type, Component[]> dic = new();
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
foreach (var field in mono.GetType().GetFields(flags))
{
Attribute attribute = GetFindCompAttribute(field);
if (attribute == null) continue;
Type type = field.FieldType;
var components = GetComponentsByType(mono, type, dic);
switch (attribute)
{
case FindComponentAttribute componentAttribute:
HandleFindComponent(mono, field, components, componentAttribute);
break;
case FindComponentsInChildrenAttribute:
HandleFindComponentsInChildren(mono, field, components);
break;
}
}
}
private static Attribute GetFindCompAttribute(FieldInfo field)
{
var attr1 = field.GetCustomAttribute<FindComponentAttribute>();
if (attr1 != null)
{
return attr1;
}
var attr2 = field.GetCustomAttribute<FindComponentsInChildrenAttribute>();
return attr2;
}
private static void HandleFindComponent(Component mono, FieldInfo field, Component[] components,
FindComponentAttribute attribute)
{
if (string.IsNullOrEmpty(attribute.goName))
{
field.SetValue(mono, components[0]);
return;
}
if (attribute.getChild)
{
foreach (var component in components)
{
if (component.transform.parent.name == attribute.goName)
{
field.SetValue(mono, component);
break;
}
}
}
else
{
foreach (var component in components)
{
if (component.name != attribute.goName) continue;
field.SetValue(mono, component);
break;
}
}
}
private static void HandleFindComponentsInChildren(Component mono, FieldInfo field, Component[] components)
{
field.SetValue(mono, components);
}
private static Component[] GetComponentsByType(Component mono, Type type, Dictionary<Type, Component[]> dic)
{
if (dic.TryGetValue(type, out var components)) return components;
if (type.IsArray)
{
type = type.GetElementType();
}
var selfComponent = mono.GetComponent(type);
var childrenComponents = mono.GetComponentsInChildren(type, true);
components = selfComponent != null
? new[] { selfComponent }.Concat(childrenComponents).ToArray()
: childrenComponents;
if (components == null || components.Length == 0)
{
#if UNITY_EDITOR
Debug.Log($"无法找到{type}对象");
#endif
return null;
}
dic.Add(type, components);
return components;
}
}
}