文章目录
前言
有时需要查找一个GameObject有没被场景里的哪些组件引用,直接查效率比较低,而且还可能漏了,这里做了一个小工具来查找
一、效果图
二、思路
想知道一个组件有没有引用到我们的GameObject,可以获取这个组件的所有字段,即FieldInfo。 然后遍历所有的FiledInfo, 如果FiledInfo是GameObject或者是Component类型,那么我们即可获取到这个FieldInfo所对应的GameObject,接下来判断这个GameObject和我们想查询的GameObject是不是同一个。是的话,即代表这个组件引用了我们查询的GameObject.
三、实现
ok,既然有了思路,接下来,我们来实现这个功能。
1. 获取所有的物体
var objs = Resources.FindObjectsOfTypeAll(typeof(Transform));
Resources.FindObjectsOfTypeAll()方法找到的物体不仅包括 Hierarchy 窗口,也包括Project窗口里的预制体。一般情况下我们只想查找场景里的引用,预制体的不要。不然一般会查出两份一样的。接下来我们来过滤下
2. 过滤掉一些不要的物体
2.1 只获取是根节点的Transform
为什么只获取是根节点的Transform呢。因为我们可以通过rootTran.GetComponentsInChildren<Component>() 来拿到根节点和它所有子节点的组件。所以拿到了所有根节点,也就相当于拿到了所有组件。
private static List<Transform> GetRootTranList(Object[] objs)
{
List<Transform> parentTranList = new List<Transform>();
foreach (var o in objs)
{
var tran = o as Transform;
if (tran.parent == null || tran.parent.name.Equals(CANVAS_ENVIROMENT))
{
//过滤掉预制体
if (IsInHierarchy(tran.gameObject))
{
parentTranList.Add(tran);
}
}
}
return parentTranList;
}
看上面的代码:
if (tran.parent == null || tran.parent.name.Equals("Canvas (Environment)"))
根节点可以通过tran.parent == null 来判断,这个好理解。
那为什么父节点名字为"Canvas (Environment)"也算呢: 当我们双击一个UGUI预制体的时候,可以在Hierarchy里窗口看到它的层级,不过Unity会自动添加一个"Canvas (Environment)"的根节点,所以它的根节点也就变成了这个。这种情况我们也想查询,所以把它也加进来。
2.2 过滤预制体
怎么过滤预制体呢,可以通过 gameObject.scene.path 来判断. 在场景里的GameObject这个路径不为空,预制体则为空。
所以我们可以根据它是否为空来判断。
要注意的是双击进来的UGUI预制体,即前面说的根节点为"Canvas (Environment)",这个路径也为空,但是我们想把它也加进来,所以当根节点名字为这个名字时,我们也返回true. 如以下代码
private static bool IsInHierarchy(GameObject go)
{
if (!string.IsNullOrEmpty(go.scene.path))
{
return true;
}else if (go.name.Equals(CANVAS_ENVIROMENT))
{
return true;
}
return false