U3D 性能优化

官方优化文档--优化图像性能
http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

Unity3D性能优化专题
性能优化是一个异常繁琐而又涉及到项目开发的方方面面的一个过程,它的本质是在运行时的一个时间里尽量完美展示丰富的内容。
实现优化能够经过优化资源、渲染、粒子、物理等模式;
也能够经过修改模型大小、减小纹理尺寸并结合Unity3D的一些相关特性来提高游戏的性能。
随着移动端的设备硬件能力的提高,如何使用尽量优化的资源和程序效率来展示出更多的细节内容就成为了每一个开发者都应该思考的内容,这也使得优化变成了项目开发中很是重要的一环。
***********
首先介绍下draw call(这个东西越少你的游戏跑的越快):
在游戏中每个被展现的独立的部分都被放在了一个特别的包中,咱们称之为“描绘指令”(draw call),而后这个包传递到3D部分在屏幕上呈现出来。这就和你但愿你的亲友收到准备好的圣诞礼物须要包装好而后穿过城市准时放在他应该出现的地方同样没什么不一样。你的CPU来完成包装和传递他们的活,同时会消耗不少的带宽,因此最终分配好这些关键性资源很重要。目前,真正可怕的事情是从描绘指令消耗远景开始,每个独立的飞溅到地板上的血迹和一个角色或者一具死尸消耗的字节是同样的多的:他们都消耗一样的描绘指令。除此以外,没有什么更多的差异。
那么如何下降 draw call 呢??那么咱们就用到Culling(剔除)技术。若是不该用这个技术,电脑是无论3721把场景里全部的东西都送去渲染的。看得见的也渲染,看不见得照样也送去渲染。很傻是吧,那咋办呢。得告诉电脑,那个你
看得见的渲染,看不见的就算了。因而就有了
1.视锥体剔除(Frustum Culling)这个unity系统自带了好像,就不用操心了。
2.遮挡剔除(Occlusion Culling
Unity 3专业版内置了一个强大的 Occlusion Culling 插件 Umbra免费的
遮挡剔除(Occlusion Culling
遮挡剔除是一种什么样的特性呢, 当一个物体被其余物体遮挡住而不在摄像机的可视范围内时不对其进行渲染。. 遮挡剔除在3D图形计算中并非自动进行的。由于在绝大多数状况下离 camera 最远的物体首先被渲染,靠近摄像机的物体后渲染并覆盖先前渲染的物体(这被称为重复渲染,无效渲染"overdraw"). 遮挡剔除不一样于视锥体剔除. 视锥体剔除只是不渲染摄像机视角范围外的物体而对于被其余物体遮挡但依然在视角范围内的物体则不包括在内. 注意当你使用遮挡剔除时你依然受益于视锥体剔除(Frustum Culling.
***********
Unity(或者说基本全部图形引擎)生成一帧画面的处理过程大体能够这样简化描述:引擎首先通过简单的可见性测试,肯定摄像机能够看到的物体,而后把这些物体的顶点(包括本地位置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好,而后通知图形API——或者就简单地看做是通知GPU——开始绘制,GPU基于这些数据,通过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。
Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐个物体进行的,对于每一个物体,不仅GPU的渲染,引擎从新设置材质/Shader也是一项很是耗时的操做。所以每帧的Draw Call次数是一项很是重要的性能指标,对于iOS来讲应尽可能控制在20次之内,这个值能够在编辑器的Statistic窗口看到。 Unity内置了Draw Call Batching技术,从名字就能够看出,它的主要目标就是在一次Draw Call中批量处理多个物体。只要物体的变换和材质相同,GPU就能够按彻底相同的方式进行处理,便可以把它们放在一个Draw Call中。Draw Call Batching技术的核心就是在可见性测试以后,检查全部要绘制的物体的材质,把相同材质的分为一组(一个Batch),而后把它们组合成一个物体(统一变换),这样就能够在一个Draw Call中处理多个物体了(其实是组合后的一个物体)。
Draw Call Batching存在一个缺陷,就是它须要把一个Batch中的全部物体组合到一块儿,至关于建立了一个与这些物体加起来同样大的物体,与此同时就须要分配相应大小的内存。这不只会消耗更多内存,还须要消耗CPU时间。特别是对于移动的物体,每一帧都得从新进行组合,这就须要进行一些权衡,不然得不偿失。但对于静止不动的物体来讲,只须要进行一次组合,以后就能够一直使用,效率要高得多。 - See more at: http://ravenw.com/blog/2011/10/14/unity-optimization-of-draw-call/#sthash.0WfH4KnX.dpuf
***********

输出设置相关:
1:最终输出的时候,unity - edit - project setting - player , other settings - script call optimization 改为 快速, 但没有例外. fast but no exceptions
2: unity - edit - project setting - time , maximum allowed timestep 改为0.1
3:

常规优化
1: 联结(combine)优化
显卡对于一个含100个面片的物体的和含1500个面片的物体的渲染消耗几乎是等价的。因此若是你有N个同一材质的东西,那么把他们联成同一个物体再统一用一个material那么对于显卡的渲染消耗就要下降N倍。
unity里再联结,这个要怎么作呢,其实也挺简单的,常常看Island Demo项目的人应该很早就注意到里面的石头这些都是连在一块儿的,缘由就在这里,他提供了现成就脚本实现联结。
先到Island DemoAssets/Script下找到CombineChildren.csMeshCombineUtility.cs两个脚本复制到本身的项目文件(咱们要用的只是前者,但他会调用后者,没有后者unity会报错,因此把后者扔到项目里无论就好)
而后把你项目里那些用同一Materials的东西扔到一个空物体里面去,再把CombineChildren.cs贴到那个空物体上,搞定!
2: 模型
(1)只用一个mesh renderer, 少用多materials, 最多3
每一个角色尽可能使用一个 Skinned Mesh Renderer
这是由于当角色仅有一个 Skinned Mesh Renderer 时, Unity 会 使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个 Skinned Mesh Renderer 时才会启动。
(2)模型骨骼不超过30.
(3)尽可能减小面 300-1500
(4)模型尽可能不要分开, 若是多个模块, 会屡次调用dc
(5)通常角色应该没有 IK 结点
这是由于角色的动做大多数都是事先设定好的,并不须要通过 IK 操做来进行实时计算( Rogdoll 除外),因此在模型导入时,不要将 IK 结点一块儿导入。
(6) 不要附加 Animation Component 在静态实体上附加 Animation 部件虽然对结果没有影响,但却会增长必定的 CPU 开销来调用这一组件,因此尽可能去掉该组件。

3:尽可能不用像素光(pixels Lights)
4:不用 软阴影(soft shadow), 或者不用阴影(No Shadows)
灯光能不用就不用, 阴影能够用面来代替.
5:少用实时灯光, 尽可能使用lightmap
http://blog.sina.com.cn/s/blog_409cc4b00100no8y.html
动态实时灯光相比静态灯光,很是耗费资源。因此除了能动的角色和物体(好比能够被打的处处乱飞的油桶)静态的地形和建筑,统统使用Lightmap
强大的Unity内置了一个强大的光照图烘焙工具Beast,这个东东是Autodesk公司的产品
6:transformOnGUI (运算上的优化远比不上 绘制效率上的优化,少个dc可能就比得上这些了)
http://fredxxx123.wordpress.com/2013/05/22/unity%E6%80%A7%E8%83%BD%E5%84%AA%E5%8C%96%E4%B9%8B%E5%B0%8F%E6%B8%AC%E8%A9%A6/
// transfrom
少用transform, 多用 myCachedTransform
頻繁使用該物件的地方,就是先把該物件cache起來,理論上就會避免這種没必要的開銷。
※這也可延伸至其余是property的變數。例如:transform.position
***直接使用的版本:
public class TestUnit : MonoBehaviour
{
void Update()
{
var t = this.transform;
t = this.transform;
t = this.transform;
t = this.transform;
t = this.transform;
}
}
***cache 使用的版本:
public class TestUnit : MonoBehaviour
{
Transform myTransform;
void Start()
{
myTransform = transform;
}

void Update ()
{
var t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
}
}
// OnGUI
空物件版本:
public class TestUnit : MonoBehaviour
{
}
外加一個空白OnGUI的版本:
public class TestUnit : MonoBehaviour
{
void OnGUI()
{ }
}
實際上是被GUI.Begin()GUI.End()所佔據,function自己是無辜的~~
非必要避免使用OnGUI(),即便它裡面甚麼事情都沒作!
如需使用,請盡可能集中到同一個OnGUI()底下執行繪製,好避免Begin End的開銷。

7:动态物体的相关优化

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

8:静态物体的相关优化

下面咱们来看静态物体,静态物体也是要控制面数和顶点数,顶点数少于500个。static是不会进行移动缩放、旋转的,把它标记为static,固然他们的材质是同样的。不要添加animation组建,对于静态物体来讲,这个组件毫无心义,能把他丢掉就丢掉,由于这对CPU的消耗是很是客观的。
9:音频程序的优化
关于音频时间的播放,好比背景音乐,建议使用MP3压缩格式,好比音效,要求数据尽快加载,这些数据比较小就能够,使用WAVAIF未压缩音频格式。关于程序包的优化,不少开发者会埋怨说打出来的包太大,如今介绍减小程序包的方法,首先使用压缩格式的纹理,以显卡的压缩格式保存,使用压缩网格和动画数据。网格压缩是先采用量化处理,固然这个压缩是保证在包里面的数据小,但运行时占用的内存没有减小,由于咱们并无把顶点删除,可是对动画数据来讲,动画数据通过压缩处理后下降,能够减小游戏列层。

关于代码尽可能不要使用System.xml,咱们建议使用Mono.xml。启用Stripping来减小库的大小,使用剥离方式。

10:引擎相关优化和物理相关优化
下来是引擎相关的优化,例如光照设置、相继设置、粒子特效、物理特效等。那拿光照设置来讲,光源所有的实时光照这是很恐怖的,每一次实施光照表明着每一次使用消耗,怎么优化?有人使用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是须要很好利用到。

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

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

13:



*********************************
*********************************
*********************************
最近一段时间一直在作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 。地形的混合操做是很耗时的,应该尽可能避免。能合并的纹理尽可能合并。
4、 纹理
纹理格式
建议 png tga 。不用转成 ios 硬件支持的 PVRTC 格式,由于 Unity 在发布时会帮你自动转的。
纹理尺寸
长宽小于 1024 。同时应该尽量地小,够用就好,以保证纹理对内存带宽的影响达到最小。
支持 Mipmap
建议生成 Mipmap 。虽然这种作法会增长一些应用程序的大小,但在游戏运行时,系统会根据需求应用 Mipmap 来渲染,从而减小内存带宽。
检查 Alpha
若是纹理的 alpha 通道均为 1 ,则用 RGB 24 位纹理来代替 RGBA 32 位纹理。(听说 Unity 内部会进行自动检测)
5、 光源
光源“ Important ”个数
建议 1 个,通常为方向光。“ 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 html

相关文章
相关标签/搜索