unity3d foreach的foreach 性能问题解决了么

Unity3D - 图形性能优化:批量draw call
发布时间: 17:25:27
Unity官方文档之“图形性能优化-批量draw
call”的翻译,。
Draw Call Batching 批量Draw Call
To draw an object on the screen, the engine has to issue a draw call to the graphics API (e.g. OpenGL or Direct3D). Draw calls are often seen as expensive, with the graphics API doing significant work for every draw call, causing performance overhead on the
CPU side. However this is not the case. The expensive part is the changing of the resources accessed by the GPU between the draw calls as it triggers a graphics driver validation each time. The emphasis should be on reducing the batch count, rather than the
draw call count.
为了在屏幕上绘制一个物体,引擎需要发一个draw call给图形API(比如OpenGL或Direct3D)。对每个draw call,图形API要做可观的工作,所以通常认为draw
call开销大,它消耗CPU性能。然而,这还不是关键,开销大的地方是draw call之间GPU变换访问资源,因为每个draw call都要触发一次图形驱动程序工作。降低批量数比draw call数更重要。
Unity uses static batching to address this. The goal of the static batching is to regroup as many meshes in less buffers to get better performance, rendering giant meshes instead of a lot of small meshes which is inefficient. Unity will only loop on the same
resources to render different ranges of these resources. Effectively it executes a series of fast draw calls for each staticcally batched mesh.
Unity使用静态批处理方法来降低批量处理。静态处理的目的是重组许多网格来获取更好的性能,这样缓存更少,渲染大网格而不是很多低效的小网格。Unity仅仅循环处理相同资源来渲染这些资源的不同种类。针对每个静态调用批量过的网格,Unity高效执行连续的快速绘制调用。
Built-in batching support in Unity has significant benefit over simply combining geometry in the modeling tool (or using the&CombineChildren&script from the Standard Assets
package). In Unity 5.0, there is only one build of the index buffer on start and then a draw call is submitted for each sub mesh of that big mesh for each visible sub mesh.
Unity支持的内置批量处理,比在建模工具中(或使用Standard Assets包中的CombineChildren脚本)简单的合并几何,有更好的效果。Unity 5.0中,开始时只构建一个索引缓存,然后针对大网格的所有可视子网格提交一次绘制调用。
Materials 材质
Only objects sharing the same material can be batched together. Therefore, if you want to achieve good batching, you need to share as many materials among different objects as possible.
只有共用相同材质的物体才可以一起批处理。因此,如果想获得好的批处理效果,你需要对不同物体尽可能多的共用相同的材质。
If you have two identical materials which differ only in textures, you can combine those textures into a single big texture - a process often called&. Once textures are in the same atlas, you can use a single material instead.
如果两个独立的材质仅仅纹理不同,你可以合同两张纹理到一个大纹理上——这常常叫做打纹理图集。一旦纹理在同一个图集上,你就可以用一个材质来代替两个材质了。
If you need to access shared material properties from the scripts, then it is important to note that modifying&&will
create a copy of the material. Instead, you should use&&to keep material shared.
如果你需要在脚本中访问共享材质的属性,请注意修改Randerer.material会创建材质的一份拷贝,你应该用Renderer.sharedMaterial来保持材质共享。
Dynamic Batching 动态批量
Unity can automatically batch moving objects into the same draw call if they share the same material and fulfill other criteria. Dynamic batching is done automatically and does not require any additional effort on your side.
Unity可以自动批量处理移动的物体到相同draw call,如果他们共享相同的材质并且遵守其它标准。动态批处理是自动完成的,你不需要做任何事。
Tips:小提示:
Batching dynamic objects has certain overhead&per vertex, so batching is applied only to meshes containing less than&900&vertex attributes in total.
批处理动态物体在每个顶点有一定开销,所以批处理只对总共包含小于900个顶点的网格进行。
If your shader is using Vertex Position, Normal and single UV, then you can batch up to 300 whereas if your shader is using Vertex Position, Normal, UV0, UV1 and Tangent, then only 180 verts.
Please note: attribute count limit might be changed in future
如果你的着色器使用顶点位置、法线和UV值,那么最多可以批处理300个顶点;如果你的着色器使用了顶点位置、法线、UV0、UV1和切线,那么只能处理180个顶点。
请注意:属性的数量限制将来可能变化。
Generally, objects should be using the same transform scale.
一般的,物体应该使用相同的缩放。
The exception is non-un if several objects all have different non-uniform scale then they can still be batched.
例外是非统一缩放的物体:如果几个物体用不同的非统一缩放,那么它们可以批处理。【译注:这里的意思是,如果一个缩放(1,1,1)的物体和一个缩放(2,2,2)的物体不可以批处理;但是,缩放(1,2,1)的物体和缩放(1,3,1)的物体可以批处理】
Using different material instances - even if they are essentially the same - will make objects not batched together.
Objects with lightmaps have additional renderer parameter: lightmap index and offset/scale into the lightmap. So generally dynamic lightmapped objects should point to exactly the same lightmap location to be batched.
Multi-pass shaders will break batching. Almost all unity shaders supports several lights in forward rendering, effectively doing additional pass for them. The draw calls for “additional per-pixel lights” will not be batched.
Objects that receive real-time shadows will not be batched.
使用不同材质的实例,即使他们本质上是相同的,但是物体不批处理到一起。含有lightmaps的物体有附加的渲染参数:lightmap索引和偏移/缩放,所以,一般来说,为了批处理动态lightmap的物体,应该严格的指向相同的lightmap部位。
多通道着色器会破坏批处理,几乎所有unity着色器在前向渲染时都支持几个灯光,并且为它们添加高效的附加通道。“附加的逐像素灯光”的draw call不会被批处理。
接受实时阴影的物体也不会被批处理。
Static Batching 静态批处理
Static batching, on the other hand, allows the engine to reduce draw calls for geometry of any size (provided it does not move and shares the same material). Static batching is significantly more efficient than dynamic batching. You should choose static batching
as it will require less CPU power.
在另一方面,静态批处理允许引擎为任何尺寸的几何降低draw call(如果它不移动,并且共用相同材质)。静态批处理比动态批处理效果好得多,因为它需要消耗更少的CPU,所以你应该选择静态批处理。
In order to take advantage of static batching, you need explicitly specify that certain objects are static and will&not&move, rotate or scale in the game. To do so, you can mark objects as static using the Static checkbox
in the Inspector:
为了利用静态批处理,你应该显式指定某些物体是静态的,并且它不移动、旋转或缩放。你可以在检视器(Inspector)中使用Static checkbox来标明物体是静态的。
Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might
not always be a good idea - sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.
使用静态批处理需要额外的内存来存储合并的几何。如果几个物体在批处理前共用相同的几何,那么在编辑器中或运行时,对每个物体都会创建一份几何的拷贝。批处理不一定是好的,有时候对有些物体,你需要牺牲渲染性能来避免批处理,以减少内存消耗。比如,把一片浓密森林中的每一棵树标注为静态的,会消耗很大的内存。
Static batching does not reduce batches instead of draw calls. Their number stays the same, but they are a lot faster with static batching.
静态批处理降低批次,而不是draw call数,draw call还是那么多,但是使用静态批处理可以获得更快的效果。
Other batching tips 其它批处理提示
Currently, only&&and&&are batched. This means that skinned meshes, cloth, trail renderers and other types of rendering components arenot&batched.
目前,只有Mesh.Renderers和粒子系统使用批处理,蒙皮网格、衣服、尾迹渲染和其它类型的渲染组件并没有批处理。
Semitransparent shaders most often require objects to be rendered in back-to-front order for transparency to work. Unity first orders objects in this order, and then tries to batch them - but because the order must be strictly satisfied, this often means less
batching can be achieved than with opaque objects.
半透明shader为了透明效果的需要,常常要求物体以由后向前的顺序渲染。Unity首先要求物体以这种顺序,然后试着批处理它们,但是因为顺序被严格限制了,所以,不透明物体比透明物体会获得更好的批处理效果。
Some parts of Unity’s rendering do not have batc for example rendering shadow casters, camera’s depth textures or GUI will not do batching.
Unity的有些渲染还没实现批处理,比如渲染阴影投射、相机的深度纹理或者GUI将不会做批处理。
来源:http://blog.csdn.net/ynnmnm/article/details/java foreach 语句性能问题 - 开源中国社区
当前访客身份:游客 [
当前位置:
这里请教一下大家关于for each语句相比于for while 等循环语句的性能比较问题
昨晚遇到了这个问题,写了记录了一下,但是发现又有些问题,于是乎又找了一些资料,看到了,但是还是不明确,希望大家能够一起讨论一下
共有9个答案
<span class="a_vote_num" id="a_vote_num_
能用for each尽量用for each. 这个语法编译器会做优化的。如果是一个数组,则相当于调用下面的代码
for(int i=0, len=array. i& i++) {
} 如果是Iterable的子类,比如List,Set。则相当于调用如下代码
Iterator iter = iterable.iterator();
while(iter.hasNext()) {
Object obj = iter.next();
} 所以你性能没有问题的。但是如果你希望在循环体内获得当前循环的下标。那么建议你直接用for while循环.因为如果你用for each或浪费一些变量空间
int i = -1;
for(Object o : array) {
System.out.println(i);
对应下面代码
for(int j=0, len=array. j& j++) {
System.out.println(i);
很明显,浪费了一个j的空间
--- 共有 5 条评论 ---
: 恩恩,确实是这样,确实是因为使用了String进行转换赋值引起的,感谢兄台啊
(2年前)&nbsp&
: 不是for each耗时, 是for each做了强制转换和变量赋值。你在其他的里改成String s = list.get(i); 以一样耗时了
(2年前)&nbsp&
: 上面博客那里弄了个链接,可以直接点击进去看的
(2年前)&nbsp&
: 你博客什么代码,给个地址吧
(2年前)&nbsp&
感谢你的帮忙哈,但是为什么我的那个博客里面的代码打印出来的时间差会有那么大呢,让人感觉for each就是很耗时的那种
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
关注这种细节真的很没必要。从应用角度来讲,没差别的。
--- 共有 1 条评论 ---
感谢你的帮助,但是就是说我写的那个博客里面,那段代码运行的结果让人感觉就是foreach很耗时啊
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
如果实在是搞不清楚,
可以写同样功能的语句, 从bytecode分析一下.
我觉得看应用的场合, while的性能应该更好.
楼上的回答有点问题, 人家是问性能, 不是问内存, 省一个整数的空间意义不大.
--- 共有 1 条评论 ---
嗯嗯,感谢,是得看应用的场合,字节码文件的话现在还不会分析,,,我试试看看使用不同的数组、List等看看有什么不一样吧
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
遍历个10万个元素的数组,List,看看时间相差多少,能接受就用,其实不差那点性能损失的。
--- 共有 1 条评论 ---
首先感谢一下。
这个我也试了,这里是我的博客,里面的代码就是测试的情况,http://blog.csdn.net/yannanying/article/details/
但是后面有位仁兄评论提醒了我,我觉得单独这样还是不能拿出来直接说怎么样怎么样,觉得应该要看场合,比如说打印数组的时候,打印List的时候等等
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
感谢以上几位仁兄的帮助,小弟在
兄台的解说下已经明白了
<span class="a_vote_num" id="a_vote_num_
for each本来就是用于遍历集合,为了方便访问集合中的元素,把元素对象进行赋值引用是很正常的,也是回调结构所必需的,怎么说得好像赋值引用是多余的不应该的。。。
--- 共有 3 条评论 ---
: 恩恩,感谢
(2年前)&nbsp&
: 跟SmallWarm说的是一致的,for-each交由编译器自动分析优化,把遍历所需要代码的补上。如果遍历数组,则跟循环数组一样;如果是集合,则调用Iterator接口遍历。换句话说,for-each只是给你代步,别胡想以为for-each是换用其他算法。
(2年前)&nbsp&
感谢,请问你是怎么理解的呢
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
这个有什么意义?真的会由于for循环导致性能问题么?也许是算法的问题。或者如果真的有性能问题,是不是可以考虑其他的什么方案?
--- 共有 1 条评论 ---
额,是我误以为的。。。
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
for each只是语法糖,运行的时候都是一样
<span class="a_vote_num" id="a_vote_num_
瓶颈不在此,排查下其他地方吧。
更多开发者职位上
有什么技术问题吗?
炎南鹰的其它问题
类似的话题君,已阅读到文档的结尾了呢~~
总结使用Unity3D优化游戏运行性能的经验
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
总结使用Unity3D优化游戏运行性能的经验
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口【风宇冲】Unity3D性能优化:DrawCall优化
原创文章如需转载请注明:转载自
DrawCall优化
二 Skinned Mesh
三 合并要求对比
五 场景制作建议
DrawCall优化合并,也叫批处理,即DrawCall
Batching. 通过减少Draw call数提高性能。
分为Dynamic Batching和 Static Batching
不需要任何操作,只要共享材质(即使是不同的Mesh模型也可以),就会自动被合并。可以自由移动旋转。但有以下使用要求:
(1)单个Mesh的vertex attribute总数不超过900.
即 vertex* attributeCount & 900
例如一个Mesh有pos,uv,normal,那么attributeCount为3,
也就是顶点数量不超过300个。
(2)游戏对象使用相同模型和材质时,只有相同缩放(即xyz等比缩放,浮点尾数可以有细微差)的会被合并。
(1,1,1)与(1,1,1)
(2,2,2)与(2,2,2)
(0.5,0.5,0.5)与 (0.5,0.5,0.5)
(2,2,2)与(2,2,2.0001)
(3)场景烘焙:烘焙后同材质将不会被烘焙。lightmap
有隐藏的材质参数:offset/scale, 所以使用lightmap的物体不会被合并
(4)Shader不能使用多Pass:多Pass的Shader会破坏Dynamic Batching
运行游戏后将一组游戏对象的多个模型会被动态合并为1个。这组游戏对象所有使用同一材质的在一个DrawCall来完成。这些游戏对象运行后无法移动缩放旋转。但是Drawcall一定是最大化合并的,并且不受动态合并的诸多限制(见下文详述)。
注意:即使物体都使用了同样的模型,在batch后每一个物体都会创建一份模型对应的geometry,在新的Combined
Mesh里。所以过多的batch会增加内存占用。例如场景里的树群就不适合Static Batch,而适合动态合并。
(1)MeshRenderer勾选Batching Static: 勾了即可
(2)代码中使用UnityEngine.StaticBatchingUtility实现(可以在任何平台调用):
& & 1)将所有要合并的静态物体(不须勾Batching
Static)放入统一一个root
2)StaticBatchingUtility.Combine(root);
之后就合并好了!
勾选Batching Static:
完全自动合并,在MeshFilter里显示的是 Combined
Mesh(root:scene)。合并后不能移动
StaticBatchingUtility:
合并到一个游戏对象下。合并后可以移动父节点游戏对象
Skinned Mesh Renderer
没有任何batching, 故不是人物的话尽量少用。
(1)修改Renderer.material将会创建一份新的material,应使用Renderer.sharedMaterial来保持材质公用。
(2)可以使用Mesh.Optimize()&优化模型。导入模型不需要调用此接口,在导入模型至Unity3d时已自动处理。
代码创建的模型有可能需要调用此接口来优化。
三 合并要求对比
只能是MeshRenderer不能是SkinnedMeshRenderer
2 Shader必须是单Pass
3 不能被场景烘焙(不能标注为Light map
4 网格模型文件总点数要求
5 网格模型单个文件点数要求
6 限制缩放
7 限制位移旋转
三种方式:
1 动态合并
&&& 优点:
内存消耗小
可以自由位移旋转
&&& 缺点:
要求众多()
2 标记Light map static合并
&&& 优点:
最方便快捷,要求最少
&&& 缺点:
完全不能移动
&内存有消耗
只能处理在Scene中默认放置的物体
3 代码StaticBatchingUtility合并
&&& 优点:
&方便快捷,要求少
可整体移动
可处理代码动态加载的场景或物体
&&& 缺点:
内存有消耗
代码合并是要求最少的,并可以整体移动。而动态合并可以移动旋转,并做Animation动画。故推荐StaticBatchingUtility
+ 动态合并。
五 场景制作建议
美术人员在制作某场景时,尽量:
静态物体:使用静态合并
1 用Mesh Renderer,也就是不绑定骨骼
2 不是Wrap循环UV的贴图,尽量合并到一张大图集
标注Batching Static即可
动态物体:使用动态合并,动画可以用Unity的动画去做
2 不参与场景烘焙
3 相同物体相同缩放
4 单个Mesh的vertex attribute总数不超过900.
5 Shader单Pass
满足条件Unity自动优化
(不满足动态合并要求的。场景动画可以用骨骼动画去做。但应尽量避免或者少的使用这种方式。因为没有Drawcall优化效率较低)
要关闭动态合并在subshader里加以下代码即可
Tags&{&"DisableBatching"&=&"true"&}
如果是非Mobile端可以考虑使用GPU Instancing
如果是有超级多的人,可考虑使用顶点动画提高性能。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 unity3d性能优化 的文章

 

随机推荐