原文地址: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多毫秒。
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_34f644c7352c94e.png)
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_562d10fc6b8b7f3.png)
复制代码
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的机会不会很多。
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_6bbf22b0510712a.png)
3.下面就是重头戏了,喜闻乐见的GameObject.Find。为了更加贴近真实情况,LZ在场景中添加了很多很多空GameObject,可是结果却让LZ和小伙伴都惊呆了。
复制代码
1
|
obj[i] = GameObject.Find(
"Sprite"
);
|
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_c103531bca110cb.png)
尼玛这不科学,LZ可是加了不下100个物体来进行干扰工作啊(╯‵□′)╯︵┻━┻,为毛它用时最短!于是LZ不甘心又换了一个物体寻找。
复制代码
1
|
obj[i] = GameObject.Find(
"GameObject1"
);
|
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_db1a76c0e06895e.png)
这才是想要的结果好么。好吧,哪位大神能帮忙解释下这是为啥。。
4.接下来是使用Tag进行访问。需要把目标物体的Tag进行修改下,用自己的或者系统的都行。这里LZ吧Sprite的Tag设为Finish。
![点击查看原图](http://www.ceeger.com/forum/attachment/1307/thread/2_19848_8ed1edb5ba6075d.png)
还有一种方式还没说,那就是通过将变量设为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是菜鸟,希望大神们多多提携。