【转】关于几种访问GameObject方式的效率对比

来源:互联网 发布:淘宝爆款挖掘机软件 编辑:程序博客网 时间:2024/06/07 06:08

原文地址:http://www.ceeger.com/forum/read.php?tid=12064



本人Unity经验不多,在刚入门的时候特别喜欢用Game.Find()来访问场景中的GameObject,直到后来看到一篇帖子,说是当场景中的物体多了以后用这种方法效率会很低。一般情况下使用挂载的方式或者通过tag方式访问比较好。而在后来的工作当中,受到当时技术主管的影响,某一个菜单或者界面基本都只用一个脚本来控制,脚本挂载在这个界面的最高层,访问子节点下的物体时则是通过transform.findChild方法根据名字一层一层向下去访问,这样做的好处是一切都是代码控制的,只要物体的名字不冲突,管理起来还是比较方便的。但在性能方面LZ一直有些疑问,因此做了以下测试。

1.首先是LZ习惯使用的FindChild方法。因为做界面什么,所以这里使用的NGUI插件。而代码部分写在了Awake方法中,这里循环了100W次,所以结果应该还是比较准确的。从结果可以看出,FindChild这种方法还是比较效率的,100W次只用了400多毫秒。

 


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Awake()
{
    DateTime d = DateTime.Now;
    TimeSpan ts = new TimeSpan(d.Ticks);
    startTime = Convert.ToInt64(ts.TotalMilliseconds);  //获得当前时间的总毫秒数.
    Debug.Log("开始时间:" + startTime);
    obj = new GameObject[1000000];
    for (int i = 0; i < obj.Length; i++)
    {
        obj[i] = transform.FindChild("Child").FindChild("Child").FindChild("Sprite").gameObject;
    }
    d = DateTime.Now;
    ts = new TimeSpan(d.Ticks);
    endTime = Convert.ToInt64(ts.TotalMilliseconds);
    Debug.Log("结束时间:" + endTime);
    Debug.Log("花费时间:" + (endTime - startTime) + "ms");
}
2.然后也是经常会用到的GetChild方法。代码仅仅只改了一句。可以发现使用GetChild比FindChild快了不少,但是必须知道目标的索引,是不太现实的,所以使用GetChild的机会不会很多。

复制代码
1
obj[i] = transform.GetChild(0).GetChild(0).GetChild(0).gameObject;

3.下面就是重头戏了,喜闻乐见的GameObject.Find。为了更加贴近真实情况,LZ在场景中添加了很多很多空GameObject,可是结果却让LZ和小伙伴都惊呆了。

复制代码
1
obj[i] = GameObject.Find("Sprite");

尼玛这不科学,LZ可是加了不下100个物体来进行干扰工作啊(╯‵□′)╯︵┻━┻,为毛它用时最短!于是LZ不甘心又换了一个物体寻找。

复制代码
1
obj[i] = GameObject.Find("GameObject1");

这才是想要的结果好么。好吧,哪位大神能帮忙解释下这是为啥。。
4.接下来是使用Tag进行访问。需要把目标物体的Tag进行修改下,用自己的或者系统的都行。这里LZ吧Sprite的Tag设为Finish。

复制代码
1
obj[i] = GameObject.FindGameObjectWithTag("Finish");

还有一种方式还没说,那就是通过将变量设为public通过挂载的方式来访问,这种方式可能是最受大家欢迎的了。可能也是最快的,但是可惜LZ并没有找到一种方法来记录耗时╮(╯_╰)╭。LZ做了测试,将Sprite挂载到public变量上。

复制代码
1
2
3
4
5
6
7
8
void Awake()
{
    if (sprite != null)
    {
        Debug.Log("挂载GameObject已初始化!");
        sprite.SetActive(true);
    }
}

结果点击运行后Sprite就显示了除了,这就说明sprite在Awake方法之前就已经初始化了。于是LZ推测是在构造函数的时候,于是做了测试,发现在调用构造函数时Sprite的确还为空,但是Unity不推荐在脚本中使用构造函数,因此计算耗时时会产生不确定因素。如果哪位大神有确切的测试方法记得告诉LZ啊。
最后,LZ有什么不对的地方大家都指出来啊。LZ是菜鸟,希望大神们多多提携。

0 0