Unity中究竟能不能js中使用foreachh

本文无意比较for和foreach谁效率更高,不会设计到for和foreach取值之类的等等。单纯探讨foreach会不会影响unity3d效率。
事情开端是这样的,之前在看unity优化的时候,遇见了这么一句:
尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾。那么循环10次就是240Bytes。
由于刚接触unity以及c#不久,当时没有仔细研究内在原理,只是简单相信了这个说法。于是接下来我会在代码中尽量避免使用foreach,虽然我觉得foreach真的挺好用的。
然后,现在每次遇见遍历,我都会思考为什么foreach会有这样的行为,我想知道真正的原因,直到今天,我才深入寻找资料去论证这个观点。
0x01 c#中for比foreach指令更加精简,效率更高?
关于这个说法,百度了下(懒得翻墙去google),找到一篇被广泛转发的文章:
里面代码如下:
using UnityE
using System.C
public class ForeachTest : MonoBehaviour {
protected ArrayList m_
void Start ()
m_array = new ArrayList();
for (int i = 0; i & 2; i++)
m_array.Add(i);
void Update ()
for (int i = 0; i & 1000; i++)
foreach (int e in m_array)
for (int i = 0; i & 1000; i++)
for (int k = 0; k & m_array.C k++)
初步看到代码后,很是疑惑,为什么一个简单的foreach会有这么多的内存开销。带着不解,继续搜索,直到看到知乎上这么一篇回答:
所以的疑惑在这里几乎都可以得到解答:
每一个foreach都会产生40B的内存,如果是在某个脚本的Update中使用foreach,那么每帧都会有40B的GC ALLOC。
之前在另一个地方看见过2014Unity亚洲开发者大会会议简录上有一个说法:
检测每帧都具有20B以上内存分配的选项
这几乎意味着在Update中使用foreach是不太明智的选择。关于为什么每帧20B以上内存分配不太好,我还没有仔细研究,个人猜测如果每帧20B,累计一段时间会有大量回收内存堆积,而mono回收机制里回收时间点不固定,如果隔一个较长时间点统一回收,必然会导致顿卡现象出现。
0x02 我们就不使用foreach了吗?
回答问题之前,我打算顺着 王剑飞 先生的代码验证一次,代码跟他在知乎回答里的几乎一致:
using UnityE
using System.C
using System.Collections.G
public class GCTest : MonoBehaviour {
List&int& iList = new List&int&();
int count = 10;
void Awake(){
for (int i = 0; i & i++){
iList.Add(i);
void Start () {
void Update () {
TestForeach();
void TestForeach()
foreach (var e in iList){
void TestNoForeach()
var e = iList.GetEnumerator();
while (e.MoveNext()){
void TestFor()
for (int i = 0; i & ++i){
void TestUsing()
using(var e = iList.GetEnumerator()){
while (e.MoveNext()){
请注意,这是直接在unity工程里面添加了C#脚本,使用内置的mono编译器来编译代码。
当我在Update中使用TestForeach()时,结果如下:
可以看见在我Win7 + Unity64 环境下,foreach的确有40B的GC Alloc。
接着TestForeach()中使用注释代码:
foreach (var e in iList){
foreach (var item in iList){
一共440B内存开销,这侧面印证了一个foreach会产生40B的堆内存说法。
接着在Update中使用TestNoForeach(),结果如下:
可以看到没有GC Alloc。
这样的结果似乎还是在说,不要使用foreach啊!
我又回想起来知乎上还说过:
**真相就已经出现了:
在finally里,mono编译出来的代码中有一次将valuetype的Enumerator,boxing的过程!!
What a waste!!!
这就是Unity中所带的老版本mono编译器的一个bug!**
既然是mono老版本的bug,能绕过去吗?
答案是肯定的,因为我们的项目正好是把脚本达成dll包,放入工程使用。编译脚本时,使用的是MS最新的编译器,这样是不是没问题呢?
测试一下,将新编译的dll放入工程,结果如下:
同样使用的是TestForeach()方法,不过这次已经没有GC Alloc了。
相信看完上面的朋友已经有了自己的想法了。
1.脚本直接放在Unity工程中,如果不是在Update中每帧调用,使用foreach没有太大顾虑。如果是Update中,而且是多个地方频繁使用foreach,就需要慎重考虑了。
2.脚本放入Dll中,爱咋咋地吧!
本文已收录于以下专栏:
相关文章推荐
关于这个话题,网络上讨论的很多,我也收集了一些资料,都不是很齐全,所以自己亲自测试,这里把结果分享给大家。foreach究竟怎么了?研究过这个问题的人都应该知道,就是它会引起频繁的GC Alloc。也...
网上有很多讨论关于在unity中使用foreach的方法,比如/question//answer/中热烈的讨论,以前也经常在非...
Lua代码都是运行时才编译的,不运行的时候就如同一张图片、一段音频一样,都是文件;所以更新逻辑只需要更新脚本,不需要再编译,因而Lua能轻松实现“热更新”。Ulua是一款非常实用的unity插件,它能...
在我们进行游戏战斗场景开发时,常常为了加强临场感,会在有爆炸或者撞击的时候加入震屏的效果,原理其实很简单,就是对场景主相机进行坐标和角度的变化。
设计在开始进行代码实操之前,我们先考...
原文:.cn/s/blog_930ffa0b0102vbat.html
IOS不能热更新,不是因为不能用反射,是因为
System.Reflection.A...
遮罩的意思是指对原图被遮住的部分进行一定的处理,这里使用最简单的处理就是染色,所以我们需要创建一个遮罩层,通常使用另一个图片来作为遮罩层,也就是mask图。
一、mask图的作用:跟UI...
最近在面试中遇到这样的问题,没有能够很好的回答,回来后经过试验和查验资料,发现一篇文章讲解的比较完整,直接搬过来翻译一下吧
原文地址:/q...
上次已经搭建好了框架,这里开始使用框架,本文会比较长~~因为我搞了一天,也遇到了好多坑
今天主要记录一下 c# 与 lua 的交互~~ 然后配以demo
C# 调用 lua 这个很简单,之前也有说...
他的最新文章
讲师:姜飞俊
讲师:汪木铃
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)作为Unity3D的脚本而言,c#中for是否真的比foreach效率更高? - 知乎349被浏览33346分享邀请回答28525 条评论分享收藏感谢收起Unity3D教程:尽量避免使用foreach
* 版权声明:转载时请以超链接形式标明文章原始出处和作者信息
* 本文来自:
* 本文链接:
为什么要尽量避免使用foreach。GC Alloc是造成Unity游戏偶尔卡帧的罪魁祸首。第一个循环大概会造成2.3K的GC Alloc。第二个循环则没有任何GC Alloc。所以,不要途方便,到处哪都用foreach循环。
foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用。此语句的形式如下:
foreach (type identifier in expression) statement
identifier 的类型。
identifier
表示集合元素的迭代变量。如果迭代变量为值类型,则无法修改的只读变量也是有效的。
expression
对象集合或数组表达式。集合元素的类型必须可以转换为 identifier 类型。请不要使用计算为 null 的表达式。
而应计算为实现 IEnumerable 的类型或声明 GetEnumerator 方法的类型。在后一种情况中,GetEnumerator 应该要么返回实现 IEnumerator 的类型,要么声明 IEnumerator 中定义的所有方法。
要执行的嵌入语句。
举一个代码列子:
using UnityE
using System.C
public class ForeachTest : MonoBehaviour {
protected ArrayList m_
void Start ()
m_array = new ArrayList();
for (int i = 0; i & 2; i++)
m_array.Add(i);
void Update ()
for (int i = 0; i & 1000; i++)
foreach (int e in m_array)
//big gc alloc!!! do not use this code!
for (int i = 0; i & 1000; i++)
for (int k = 0; k & m_array.C k++)
//no gc alloc!!
阅读(...) 评论()【关于foreach】为什么会出错?【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:76,557贴子:
【关于foreach】为什么会出错?收藏
如果我debug(info.name); 就会输出两个字符串。如果我debug(&1&);
却会输出一个结果是1。求大神帮看看……
达内unity3d培训全程&实战教学&,unity3d金牌讲师授课.免费unity3d课程试听中!到达内unity3d学院学习unity3d,只需4个月速成unity3d游戏工程师.
或者帮我转换成for循环也行……………………
好了……原来一切都是我2b ……
登录百度帐号推荐应用

我要回帖

更多关于 jsp使用foreach 的文章

 

随机推荐