写这个方法纯粹是为了偷懒,在功能比较简单的时候,一个个拖物体实在太显麻烦,如果能通过子物体的名字直接绑定到脚本里,确实能够省去不少时间。
原理是先检索父体下的第一子物体中有无需要的子物体,如无,则递归继续往下寻找。如有则返回。
修改部分:之前每次寻找子物体都遍历该transform下所有子物体实在是太消耗性能了,如果一个transform的子物体达到某个数量时,会变得非常卡。
因此,在首次遍历transform所有子物体的时候,使用一个List保存下来。以key为transform,value为List<Transform>的字典来保存这个transform集合。往后只要先检查字典里是否有transform这个key,如果有则直接从字典里浅拷贝添加,如果没有key,就遍历所有子物体并添加进字典。随后遍历寻找,找到了对应的子物体就break,并返回child。
以下是代码:
private Dictionary<Transform, List<Transform>> transformListDic = new Dictionary<Transform, List<Transform>>();
public Transform GetChildTransform(string childName, Transform t, bool isFindAll)
{
Transform child = t.Find(childName);
if(child == null && !isFindAll)
{
Debug.Log("!isFindAll");
return null;
}
if (t.childCount < 1)
{
Debug.Log("t.childCount = " + t.childCount);
return null;
}
else
{
List<Transform> childList = new List<Transform>();
if (transformListDic.ContainsKey(t))//检查是否有key,如果有就直接从字典里浅拷贝添加。
{
childList.AddRange(transformListDic[t]);
}
else//如果没有就添加transform下所有子物体进集合,并用transform为key来保存
{
for (int i = 0; i < t.childCount; ++i)
{
GetChildList(t.GetChild(i), childList);
}
transformListDic.Add(t, childList);
}
for (int i = 0; i < childList.Count; ++i)
{
if (childList[i].name == childName)
{
child = childList[i];
break;
}
}
return child;
}
}
public T GetChildComponent<T>(string childName, Transform t, bool isFindAll) where T : Component
{
Transform child = GetChildTransform(childName, t, true);
GameObject childObj = child.gameObject;
return (T)childObj.GetComponent<T>();
}
private List<Transform> GetChildList(Transform t, List<Transform> childList)
{
List<Transform> transforms = new List<Transform>();
foreach(Transform childT in t)
{
transforms.Add(childT);
if(childT.childCount != 0)
{
GetChildList(childT, transforms);
}
}
childList.AddRange(transforms);
return childList;
}
开玩笑的说,这是1.0版本,是刚刚实践出来的一个方法,以后可以继续拓展。
==============2.0=============
经过一段时间的使用,突然发现自己傻乎乎的在用List,每次去寻找子物体都要遍历一下,实在是不能容忍,所以我把List改为了Dictionary,2.0的代码如下:
private Dictionary<Transform, Dictionary<string, Transform>> transformMainDic = new Dictionary<Transform, Dictionary<string, Transform>>();
public Transform GetChildTransform(string childName, Transform t, bool isFindAll)
{
float time = Time.time;
Transform child = t.Find(childName);
if (child == null && !isFindAll)
{
Debug.Log("!isFindAll");
return null;
}
if (t.childCount < 1)
{
Debug.Log("t.childCount = " + t.childCount);
return null;
}
else
{
Dictionary<string, Transform> childDic = new Dictionary<string, Transform>();
if (!transformMainDic.ContainsKey(t))
{
for (int i = 0; i < t.childCount; ++i)
{
GetChildDic(t.GetChild(i), childDic);
}
transformMainDic.Add(t, childDic);
}
child = transformMainDic[t][childName];
Debug.LogFormat("耗时{0}秒", Time.time - time);
return child;
}
}
public T GetChildControl<T>(string childName, Transform t) where T : Component
{
Transform child = GetChildTransform(childName, t, true);
GameObject childObj = child.gameObject;
return (T)childObj.GetComponent<T>();
}
private Dictionary<string ,Transform> GetChildDic(Transform t, Dictionary<string, Transform> childDic)
{
Dictionary<string, Transform> transforms = new Dictionary<string, Transform>();
foreach(Transform childT in t)
{
if(childDic.containsKey(childT.name))
{
Debug.LogWarningFormat("已经存在名为{0}的组件", childT.name);
continue;
}
transforms.Add(childT.name, childT);
if(childT.childCount != 0)
{
GetChildDic(childT, transforms);
}
}
foreach(var myEntry in transforms)
{
childDic.Add(myEntry.Key, myEntry.Value);
}
return childDic;
}
其中如果只是需要这个组件本身而不需要组件上的脚本功能,那么GetChildTransform方法就能满足了。
如果需要子物体组件上的脚本,则调用GetChildComponent方法。比如
private Image NullImg;
void Start ()
{
NullImg = GetChildControll<Image>("NullImg", this.transform, true);
Debug.Log(NullImg);
}
打印出来则如图
同时还可以使用NullImg.sprite等Image组件下的方法,属性,字段,也就是完完全全获得了Image本身。
毕竟是1.0版本,而且是为了简便一些步骤想出来的方法,有不足的地方请指出。共同进步~