原文地址: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的机会不会很多。

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。

还有一种方式还没说,那就是通过将变量设为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是菜鸟,希望大神们多多提携。