在Unity中定义统一的对象搜索接口
我们经常要在Unity中以各种方式搜索对象。比如按名字搜索、按tag、layer或者是查找名字为xxx开头的对象。
本文是介绍以一种统一的接口来搜索对象。
1、定义统一的搜索接口
/// <summary> /// 游戏对象搜索接口 /// </summary> public interface IGameObjectFinder { /// <summary> /// 搜索 /// </summary> /// <param name="root">搜索的开始位置/根节点</param> /// <param name="findResult">搜索存放的结果</param> void Find(Transform root, List<Transform> findResult); }
2、定义一个使用上面搜索接口的方法
public class Finder{ /// <summary> /// 查找指定根节点下符合指定的查找器的Transform并保持到findResult中 /// </summary> /// <param name="root"></param> /// <param name="findResult"></param> /// <param name="finder"></param> public static void Find(Transform root, List<Transform> findResult, IGameObjectFinder finder) { if (root == null) { throw new Exception("root can not be null, it defines the starting point of the find path"); } if (findResult == null) { throw new Exception("findResult can not be null, it used to collect the find result"); } if (finder == null) { throw new Exception("finder can not be null, it defines how to find transform"); } finder.Find(root, findResult); } }
可以看到,2步骤只是简单调用1的接口进行搜索。但是1只是接口,有啥用?接着看。
3、实现一个查找某个组件的接口
/// <summary> /// 根据组件搜索 /// </summary> /// <typeparam name="T"></typeparam> public class GameObjectFinderByComponent<T> : IGameObjectFinder where T : Component { public void Find(Transform root, List<Transform> findResult) { foreach (var componentsInChild in root.GetComponentsInChildren<T>()) { findResult.Add(componentsInChild.transform); } } }
可以看到只要实现IGameObjectFinder就可以了。那么如果这时候想调用,应该怎么调用呢?
4、实现一个迭代查找
/// <summary> /// 迭代遍历搜索 /// </summary> public class GameObjectFinderByIteration : IGameObjectFinder { private IGameObjectFinderForIteration finderForIteration; public GameObjectFinderByIteration(IGameObjectFinderForIteration finderForIteration) { this.finderForIteration = finderForIteration; } public void Find(Transform root, List<Transform> findResult) { for (int i = 0, childCount = root.childCount; i < childCount; i++) { Transform t = root.GetChild(i); if (finderForIteration.isVaild(t)) { findResult.Add(t); } Find(t, findResult); } } }这个代码的意思就是:我先把开始节点下面的每个子节点通过另一个接口IGameObjectFinderForIteration来判断是否符合要求,是的话则加入结果列表。然后继续查找这个子结点下的其他子节点。(该搜索是不包括第一个开始节点的)
IGameObjectFinderForIteration的接口也很简单:
/// <summary> /// 迭代搜索判断 /// </summary> public interface IGameObjectFinderForIteration { /// <summary> /// 指定节点是否合法 /// </summary> /// <param name="node"></param> /// <returns></returns> bool isVaild(Transform node); }好的,这样就意味着我们要想查找某个根节点下的所有子节点(包括直接和间接的),只要实现一个IGameObjectFinderForIteration。那么OK。看看怎么按名字搜索。
/// <summary> /// 迭代遍历按名字搜索 /// </summary> public class FinderForIterationByName : IGameObjectFinderForIteration { protected readonly string NAME; public FinderForIterationByName(string name) { NAME = name; } public bool isVaild(Transform getChild) { return getChild.gameObject.name.Equals(NAME); } }
使用也很简单,加入想找transform节点下,名字为“abc”的对象,并保存在result列表里面。只要这样:
5、有什么用?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。