关于直接使用子物体名字来获得子物体的方法

写这个方法纯粹是为了偷懒,在功能比较简单的时候,一个个拖物体实在太显麻烦,如果能通过子物体的名字直接绑定到脚本里,确实能够省去不少时间。

原理是先检索父体下的第一子物体中有无需要的子物体,如无,则递归继续往下寻找。如有则返回。

修改部分:之前每次寻找子物体都遍历该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版本,而且是为了简便一些步骤想出来的方法,有不足的地方请指出。共同进步~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值