这个方法纯粹是为了偷懒而写的。 当功能比较简单的时候,一个一个的拖动对象就太麻烦了。 如果子对象可以通过名称直接绑定到脚本上,确实会节省很多时间。
原理是先在父体下的第一个子对象中查找是否有需要的子对象。 如果没有,则继续递归查找。 如果有的话返回。
修改部分:每次搜索子对象时,都要遍历变换下的所有子对象,太消耗性能。 如果一个变换的子对象数量达到一定数量,就会变得很卡。
因此,第一次遍历transform的所有子对象时,使用List来保存。 将此转换集合保存在字典中像素游戏素材,键为转换,值为列表。 以后只需要检查字典中是否有transform的key就可以了。 如果有,则直接从字典中通过浅拷贝的方式添加。 如果没有keyunity 找到所有子物体,则会遍历所有子对象并添加到字典中。 然后它遍历并搜索它。 当它找到相应的子对象时橙光游戏,它会中断并返回该子对象。
这是代码:
private Dictionary> transformListDic = new Dictionary>();
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 childList = new List();
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(string childName, Transform t, bool isFindAll) where T : Component
{
Transform child = GetChildTransform(childName, t, true);
GameObject childObj = child.gameObject;
return (T)childObj.GetComponent();
}
private List GetChildList(Transform t, List childList)
{
List transforms = new List();
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> transformMainDic = new Dictionary>();
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 childDic = new Dictionary();
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(string childName, Transform t) where T : Component
{
Transform child = GetChildTransform(childName, t, true);
GameObject childObj = child.gameObject;
return (T)childObj.GetComponent();
}
private Dictionary GetChildDic(Transform t, Dictionary childDic)
{
Dictionary transforms = new Dictionary();
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("NullImg", this.transform, true);
Debug.Log(NullImg);
}
打印出来如下图
同时unity 找到所有子物体,你还可以使用NullImg.sprite等Image组件下的方法、属性和字段,这意味着你可以完全获取Image本身。
毕竟是1.0版本,是为了简化一些步骤而想出来的方法。 有不足之处请指出。 共同进步~
文章来源:https://blog.csdn.net/DoyoFish/article/details/80689767