using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; namespace Framework.Core { [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class FindComponentAttribute : Attribute { public readonly string goName; public readonly bool getChild; /// /// 查找游戏物体组件的特性 /// /// 游戏物体名字 /// /// true => 查找对应名字对象的下一级子物体 通常名字为父物体名字 类型为子物体 /// false => 查找对应名字的对象 通常会将类型和名字对应 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 { /// /// 查找所有带标记的组件 /// 与FindComponent特性配合使用 /// public static void FindComponents(this Component mono) { Dictionary 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(); if (attr1 != null) { return attr1; } var attr2 = field.GetCustomAttribute(); 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 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; } } }