using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace XericLibrary.Runtime.MacroLibrary { public static class MacroObject { #region 对象操作 /// /// 获取此枚举器在给定索引下的值 /// /// /// /// /// /// public static T SelectIndex(this IEnumerable target, int index) { int nowIndex = 0; foreach(var item in target) if(nowIndex++ == index) return (T)item; throw new IndexOutOfRangeException("给定的索引超出了枚举器的范围"); } /// /// 获取此枚举器在给定索引下的值,并且允许在无法找到的情况下使用null返回 /// /// /// /// /// public static T SelectIndexOrDefault(this IEnumerable target, int index) where T : class { int nowIndex = 0; foreach(var item in target) if(nowIndex++ == index) return (T)item; return null; } /// /// 按顺序获取一个节点的所有父级节点 /// /// /// public static IEnumerable GetParents(this Transform trans) { Transform target = trans.parent; while(target != null) { yield return target; target = target.parent; } } /// /// 遍历项目中父级内所有子项的差距,并找到第1个差距最大的项目; /// /// 具体是先从当前节点向上级找到第一个最少子项数量的节点, /// 以此为基准,从当前最少数量节点的子集中返回来自项目的父级(或来自项目); /// 具体是用来在场景中寻找第一个具有标识意义的节点 /// /// /// /// 倒数步骤数,基于基准父级/param> /// [Obsolete("未验证的,谨慎使用")] public static Transform GetObjectNameInParentsFilterByChildrenMeanDifferen(this Transform trans, int backStep = 1) { int minParentIndex = 0; int index = 0; int minChildCount = int.MaxValue; foreach(Transform parent in trans.GetParents()) { if(parent.childCount < minChildCount) { minChildCount = parent.childCount; minParentIndex = index; } index++; } return trans.GetParents().SelectIndexOrDefault(minParentIndex - backStep); } /// /// 获取一个变换节点下所有的子成员 /// /// /// 递归深度,0表示仅在第一子集中寻找,1表示在包含下一级在内的所有成员中寻找 /// public static IEnumerable GetChildren(this Transform trans) { #if UNITY_EDITOR if(trans == null) throw new Exception("在准备获取所有子成员时,节点为空"); #endif for(int i = 0; i < trans.childCount; i++) { yield return trans.GetChild(i); } } /// /// 递归获取一个变换节点下所有的子成员 /// /// /// 递归深度,1表示仅在第一子集中寻找,2表示在包含下一级在内的所有成员中寻找 /// public static IEnumerable GetChildrenRecursion(this Transform trans, int recursion = 1) { int newdepth = recursion - 1; foreach(var child in trans.GetChildren()) { if(newdepth > 0) foreach(var item in child.GetChildrenRecursion(newdepth)) yield return item; yield return child; } } /// /// 在所有子成员中深度优先找到第一个组件; /// 注意这只会在子项中查找。 /// /// /// /// 遍历深度,1表示仅在子集中寻找,2表示在子集中寻找,如果找不到的将在子集的子集中寻找,以此类推 /// public static IEnumerable GetComponentsInRecursionChildren(this Transform trans, int recursion = 1) where T : Component { int newRecursion = recursion - 1; //foreach(var item in trans.GetChildren()) //{ // var comp = item.GetComponent(); // if(comp == null && newRecursion > 0) // comp = item.GetComponentInRecursionChildren(newRecursion); // yield return comp; //} T[] comps; foreach(var item in trans.GetChildrenRecursion(newRecursion)) { comps = item.GetComponents(); if(comps != null && comps.Length > 0) foreach (var comp in comps) yield return comp; } } /// /// 按深度优先寻找一个组件; /// 注意这只会在子项中查找。 /// /// /// /// 遍历深度,0表示仅在子集中寻找,1表示在子集中寻找,如果找不到的将在子集的子集中寻找,以此类推 /// public static T GetComponentInRecursionChildren(this Transform trans, int depth = 1) where T : Component { T result; int newDepth = depth - 1; #if true // 如果不知道这里在找什么的可以打开调试看看 foreach(var item in trans.GetChildren()) { result = item.GetComponent(); if(result == null && newDepth > 0) result = item.GetComponentInRecursionChildren(newDepth); if(result != null) return result; } #else string info = $"{depth}. 开始在{trans.name}中寻找\r\n"; foreach(var item in trans.GetChildren()) { info += $"{depth}. > 正在{item.name}中寻找\r\n"; result = item.GetComponent(); info += $"{depth}. 当前节点{(result == null ? "不包含组件":"包含组件")}\r\n"; if(result == null && newDepth >= 0) { info += $"{depth}. 前往深层寻找 > \r\n"; result = item.GetRecursionComponent(newDepth); info += $"{depth}. 深层查找返回 < \r\n"; } if(result != null) { info += $"{depth}. 已找到结果:{result.name} \r\n"; Debug.Log(info); return result; } info += $"{depth}. 没有找到任何东西 \r\n"; } Debug.Log(info + "没有找到,空结束"); #endif return null; } /// /// 无论如何都要获取一个组件 /// /// /// public static T GetComponentAnyway(this GameObject obj) where T : Component { var component = obj.GetComponent(); if(component is null) component = obj.AddComponent(); return component; } /// /// 无论如何都要获取一个对象 /// /// /// /// public static T GetObjectAnyway(this T obj) where T : new() { if(obj is null) obj = new T(); return obj; } #endregion #region 2023/10 过时 /// /// 在所有子成员中深度优先找到第一个组件 /// /// /// /// 遍历深度,0表示仅在此处寻找,1表示在包含下一级在内的所有成员中寻找 /// [Obsolete("命名不符合规则,将使用GetComponentsInRecursionChildren替换")] public static IEnumerable GetChildrenRecursionComponents(this Transform trans, int recursion = 1) where T : Component { int newRecursion = recursion - 1; foreach(var item in trans.GetChildren()) { var comp = item.GetComponent(); if(comp == null && newRecursion > 0) comp = item.GetChildrenRecursionComponent(newRecursion); yield return comp; } } /// /// 按深度优先寻找一个组件 /// /// /// /// 遍历深度,0表示仅在第一子集中寻找,1表示在包含下一级在内的所有成员中寻找 /// [Obsolete("命名不符合规则,将使用GetComponentsInRecursionChildren替换")] public static T GetChildrenRecursionComponent(this Transform trans, int depth = 1) where T : Component { T result; int newDepth = depth - 1; foreach(var item in trans.GetChildren()) { result = item.GetComponent(); if(result == null && newDepth > 0) result = item.GetChildrenRecursionComponent(newDepth); if(result != null) return result; } return null; } #endregion } }