U3D开发性能优化札记(待增加版本)

U3D开发性能优化笔记(待增加版本)

U3D开发性能优化笔记:

.NGUI: Atlas优化;

.poolmanager使用;

.控制同屏drawcall次数;

.SHADER优化顶点和运算;

.合批与动态剔除;

.逻辑部分优化;(如看到不到的物件不要做公告板位置运算,不要播放animation)

.物理帧UPDATE降低;

.关闭垂直同步,降低图片采样,声音预加载 方案 等等 。。;

.模型骨骼不要超过32根;

.贴图不要太大,建议512 *512 以下;

.少用 CUTOFF和 aplha混合;

.3D游戏效率基本原则就是费内存省CPU 和GPU;

.NGUI ANIMATION ANIMTOR 碰撞检测 特效 渲染 这些都是性能消耗的大头;

.Occlusion Culling使用;

​.只用一个mesh renderer, 少用多materials, 最多3个;

.每个角色尽量使用一个 Skinned Mesh Renderer;

.面数问题每个模型不要超过300~1500;

.模型尽量不要分开如果多个模块会多次调用dc;

.一般角色应该没有 IK 结点.

.尽量不用像素光(pixels Lights).

.不用 软阴影(soft shadow), 或者不用阴影(No Shadows)

.灯光能不用就不用阴影可以用面来代替.

.少用实时灯光尽量使用lightmap(强大的Unity内置了一个强大的光照图烘焙工具Beast,这个东东是Autodesk公司的产品);

.transformOnGUI (运算上的优化远比不上 绘制效率上的优化,少个dc可能就比得上这些了)

.少用transform, 多用 myCachedTransform.

.动态物体的相关优化 
优化主要分为两个方向,一个是资源相关优化和引擎相关的优化。资源相关的优化,大概分为动态物体、静态物体、纹理数据、音频数据、程序包数据。对于动态物体比如NPC、怪物等,需要对面片数量的控制,大概在3002000面。1500面就可以体现人物细节,但如果是人物比较多,可能要降低面数,不要低于300。另外,一方面是控制Skinned Mesh Renderer的数量;另一方面是控制材质数量在13种。人物最好用小于30根骨骼,如果你用的骨骼越多,耗费的CPU就更多,所以在移动平台上尽量少于30根。现在我们看其他动态物体,利用Dynamic Batching进行合批。这个下雨特效并不是系统做的,是包含很多雨点的网格进行重复拷贝,然后错乱移动实现的。每一个雨点并不是一个粒子,这样能减少很多CPU的消耗,每一个整体网格都会有一个顶点的控制,通过控制顶点数量,对系统实现雨点效果来说,这是一个相当省时省力的方法。


.静态物体的相关优化 
下面我们来看静态物体,静态物体也是要控制面数和顶点数,顶点数少于500个。static是不会进行移动缩放、旋转的,把它标记为static,当然他们的材质是一样的。不要添加animation组建,对于静态物体来说,这个组件毫无意义,能把他丢掉就丢掉,因为这对CPU的消耗是非常客观的。 


.音频程序的优化 
关于音频时间的播放,比如背景音乐,建议使用MP3压缩格式,比如音效,要求数据尽快加载,这些数据比较小就可以,使用WAVAIF未压缩音频格式。关于程序包的优化,很多开发者会埋怨说打出来的包太大,现在介绍减少程序包的方法,首先使用压缩格式的纹理,以显卡的压缩格式保存,使用压缩网格和动画数据。网格压缩是先采用量化处理,当然这个压缩是保证在包里面的数据小,但运行时占用的内存没有减少,因为我们并没有把顶点删除,但是对动画数据来说,动画数据经过压缩处理后降低,可以减少游戏列层。


.代码尽量不要使用System.xml,我们建议使用Mono.xml。启用Stripping来减少库的大小,使用剥离方式。


.引擎相关优化和物理相关优化 
下来是引擎相关的优化,例如光照设置、相继设置、粒子特效、物理特效等。那拿光照设置来说,光源全部的实时光照这是很恐怖的,每一次实施光照代表着每一次使用消耗,怎么优化?有人使用LightMapping来制作静态场景,他的好处是不需要用多张实施光照,而给场景很好的光照效果。有人使用Light Probes代替实时光照,好处是完全不用怎么消耗,而且运作性能也非常高。在有些时候使用Light Probes代替光照,他能跟场景很好的融合,在一个角落里,这个任务会被阴影打得暗一些。如果说场景中确实需要一些实时光源,那么肯定是需要做过优化设置的实时光源,控制important的光源个数。如果说光源有些地方产生了交叉光,这个时候你可以通过设置Pxel Light,控制每一个光源都只接受一个动态光照,数目大概是12个。对于关闭光源的实时阴影,并不是所有平台都支持实时阴影,消耗也非常大,不建议大家使用。关于相机方面的设置,平面越近,渲染越少。我们更建议使用分层,比如远处的建筑,对于建筑物的裁减平面远一些,如果是花草,就可以使用平面就近一些。现在看一下粒子特效,粒子也是游戏中需要优化的东西,建议屏幕中最大的粒子数不要超过200,同时每个发射器发射的最大粒子数不要超过50。粒子尺寸也要尽可能小,最终在屏幕有多少像素。他们中间的像素可能会被渲染很多次,至少四五次,这时发现粒子系统仅像素就填充了更多屏幕,这时候对游戏来说非常耗费,对游戏的其他功能性能也有所影响。另外一方面,对于非常小的粒子,尽量不要开启粒子碰撞功能。


.物理相关优化,物理尽可能使用Sphere CoilliderBox Coillider等,尽量避免使用Meh Colllider等。渲染设置,避免使用Alpha Test,因为非常耗时,性价比很低。关于Sttic Batching,对静态物体进行Batch,对几何数据的大小没有限制。物体被合并后会带来一些内存消耗,比如说有控制网格的物体,用Batch会合并成大物体。Dynamic Batching目前仅支持小于900顶点的网格物体。如何理解900呢,其实就相当于900个顶点数据大小的物体,如果说使用PositionNormalUV三种属性,那么你只能Batch300个顶点。整体缩放的物体不能被Batch,除非他们的缩放值相同。之前有一个客户做特效,使用Batch机制把面片合并,最终让所有面片共享一个纹理,这时候发现这些面片没有被Batch出来,导致运行游戏时大概放三个技能就10多个招套。对于非整体用户体,他们的Batch是需要很好利用到。


.纹理合并优化 
现在来看纹理合并,纹理合并就是为了特到Batch数量,合并物体首先需要合并工具,还要修改使用纹理的网格的UV,使他们使用纹理。合并纹理主要是参照Batch,提高渲染性能。但在合并材质后需要注意的是脚本访问Renderer被拷贝。/*安挡剔除,建议使用PVS技术。建议大家使用自定义shader,例如高光效果,高光效果可能不需要做一些入射线的检测,只是简单把他的值放大也可以模拟高光效果,从而减少一些消耗。 
另外一个是用profiler,通过他给的数据进行针对性的优化。以上是跟大家介绍优化的内容,如何作出良好优化,一定要做好良好的规划,到后期就不会很麻烦,如果规划没有做好有可能会给程序带来很大压力,结果可能很不乐观。*/最后,要不断实验不断总结才能达到自己满意的效果。


.降低Drawcal的话,有如下两点小建议 
1)不要用Unity自带UI或者iGUI, NUI 或者EZ GUI 
(2)创建好的GameObject不用了就最好及时 删除 设置activefalse/移出屏幕 。 这几种方法都可以去掉该物体导致增加的Drawcall.



最近一段时间一直在做Unity IOS设备上的资源优化,结合Unity的官方文档以及自己遇到的实际问题,我把自己认为一些重要的信息罗列在下面,并尽可能对将其量化,以方便更多需要做优化的朋友。 
1、 角色 
每个角色尽量使用一个 Skinned Mesh Renderer 
这是因为当角色仅有一个 Skinned Mesh Renderer 时, Unity 会 使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个 Skinned Mesh Renderer 时才会启动。 
角色 Material 数量 
2-3  
骨骼数量 
小于 30  
面片数量 
300-1500 
一般角色应该没有 IK 结点 
这是因为角色的动作大多数都是事先设定好的,并不需要经过 IK 操作来进行实时计算( Rogdoll 除外),所以在模型导入时,不要将 IK 结点一起导入。 
2、 静态实体 
不要附加 Animation Component 
在静态实体上附加 Animation 部件虽然对结果没有影响,但却会增加一定的 CPU 开销来调用这一组件,所以尽量去掉该组件。 
网格顶点数 
小于 500 
UV 值范围尽量不要超过( 0, 1 )区间 
尽量保证 UV 值不越界,这对于将来的纹理拼合优化很有帮助。 
3、 地形 
地形的分辨率大小 
长宽均尽量小于 257 。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的 ios 设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用 Unity 自带的地形,一定也要使用 Occlusion Culling ,因为 Unity 的刷地形工具虽然方便,但却是 framekiller ,刷过之后,你会发现 drawcall 增加的非常多。 
混合纹理数量 
不要超过 。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。 
4、 纹理 
纹理格式 
建议 png 或 tga 。不用转成 ios 硬件支持的 PVRTC 格式,因为 Unity 在发布时会帮你自动转的。 
纹理尺寸 
长宽小于 1024 。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。 
支持 Mipmap 
建议生成 Mipmap 。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用 Mipmap 来渲染,从而减少内存带宽。 
检查 Alpha  
如果纹理的 alpha 通道均为 ,则用 RGB 的 24 位纹理来代替 RGBA 的 32 位纹理。(据说 Unity 内部会进行自动检测) 
5、 光源 
光源“ Important ”个数 
建议 个,一般为方向光。“ Important ”个数应该越小越少。个数越多, drawcall 越多。 
Pixel Light 数目 
1-2 个。 
6、 粒子特效 
屏幕上的最大粒子数 
建议小于 200 个粒子。 
每个粒子发射器发射的最大粒子数 
建议不超过 50 个。 
粒子大小 
如果可以的话,粒子的 size 应该尽可能地小。因为 Unity 的粒子系统的 shader 无论是 alpha test 还是 alpha blending 都是一笔不小的开销。同时,对于非常小的粒子,建议粒子纹理去掉 alpha 通道。 
尽量不要开启粒子的碰撞功能。 
非常耗时。 
7、 音频 
游戏中播放时间较长的音乐(如背景音乐) 
使用 .ogg 或 .mp3 的压缩格式。 
较短音乐(如枪声) 
使用 .wav 和 .aif 的未压缩音频格式。 
8、 相机 
裁剪平面 
将远平面设置成合适的距离。远平面过大会将一些不必要的物体加入渲染,降低效率。 
根据不同的物体设置不同的远裁剪平面 
Unity 提供了可以根据不同的 layer 来设置不同的 view distance ,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。 
9、 碰撞 
尽量不用 MeshCollider 
如果可以的话,尽量不用 MeshCollider ,以节省不必要的开销。如果不能避免的话,尽量用减少 Mesh 的面片数,或用较少面片的代理体来代替。 
10、 其他 
Drawcall 
尽可能地减少 Drawcall 的数量。 
iOS 设备上建议不超过 100  
减少的方法主要有如下几种: Frustum Culling , Occlusion Culling , Texture Packing  
Frustum Culling 是 Unity 内建的,我们需要做的就是寻求一个合适的远裁剪平面; Occlusion Culling ,遮挡剔除, Unity 内嵌了 Umbra ,一个非常好 OC 库。但 Occlusion Culling 也并不是放之四海而皆准的,有时候进行 OC 反而比不进行还要慢,建议在OC 之前先确定自己的场景是否适合利用 OC 来优化; 
Texture Packing ,或者叫 Texture Atlasing ,是将同种 shader 的纹理进行拼合,根据 Unity 的 static batching 的特性来减少draw call 。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。 
这也就是为什么会出现“ DrawCall 降了,渲染速度也变慢了”的原因。 

非运动物体尽量打上 Static 标签 
Unity 在运行时会对 static 物体进行自动优化处理,所以应该尽可能将非运行实体勾上 static 标签。 

场景中尽可能地使用 prefab 
尽可能地使用 prefab 的实例化物体,以降低内存带宽的负担。检查实体的 PrefabType ,尽量将其变成 PrefabInstance ,而不是ModelPrefabInstance 


有提出改进需求的童鞋请留言;