unity优化总结

2019-02-27  本文已影响0人  诸子百家谁的天下

编程代码规范:

代码控制

而不是引用,修改完以后,以前的不生效。

结构表示轻量对象,并且结构的成本较低,适合处理大量短暂的对象。

在表现抽象和多级别的对象层次时,类是最好的选择。

大多数情况下该类型只是一些数据时,结构是最佳的选择。

数组:内存中是连续存储的,索引速度非常快,赋值与修改元素也很简单。但不

利于动态扩展以及移动。

ArrayList: 因为数组的缺点,就产生了 ArrayList。ArrayList:使用该类时必须进行引用,同时继承了 IList 接口,提供了数据存储和检索,ArrayList 对象的大小动态伸缩,支持不同类型的结点。

ArrayList 虽然很完美,但结点类型是 Object,故不是类型安全的,也可能发生

装箱和拆箱操作,带来很大的性能耗损。对象是值类型的话会带来装箱拆箱操作

List 是泛型接口,规避了 ArrayList 的两个问题。利于动态扩展以及移动,但是搜索速度慢

闭包

片段。生命周期:变量随着其寄存对象生而生和消亡(不包括非实例化的 static 和 const

对象)。

多个方法)。通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也

就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指

的方法。如何没有涉及到闭包的话,委托代码只生产一个函数而不是一个类。lamda表达式(闭包)

MonoBehaviour 优化

以在 start 中先缓存下来,然后使用。 如果没必要每帧的逻辑,可以降低频率,方法如下:

    Void Update(){if(Time.frameCount%6==0){DoSomething();}}

Component 优化

GameObject 相关优化

NGUI 相关优化

合批 Canvas 下所有网格,这个性能热点在 5.2 版本后挪到了子线程去做减轻了

主线程的压力,而 NGUI 作为一个插件没法做到这一点,网格合批的性能热点还

是耗在主线程的 UIPanel.LateUpdate();

现的,而 NGUI 只能通过上层的不断创建 Vertex List,这样在堆内存的管理上,

UGUI 确实要好很多,带来的隐形收益就是 GC 触发次数会少很多。

UI 资源规范(内存优化)

common(DrawCall 优化);

小是 1280 * 720,让美术按照比例高度缩小到 500,

这样一张 1024*1024 的图集就可以放两张原图了,提升图集利用率。对于一些

600*400 类似大小的原图,就尽量按比例把最长边压小到 500,这样出来的图

集就是 512 * 512 而不是 1024 * 1024(内存优化);

致图集大小变大而且利用率很低的话,要把 1000*100 的原图拆分成两张图

500*100,在制作界面的时候用两个 Image 拼接即可,这样可以把 1024 的图

集缩小到 512(内存优化);

用率。合并的原则是不改变任何一个图集的大小,这样即可完全省掉一张图集(内

存优化、安装包量优化);

白蓝黄绿紫,就不要使用五张大底图了,让美术同事画一个灰色原图,Image 在

使用的时候直接按需求修改顶点色即可(内存优化);

GPU 优化

Shader优化

更多。目前在移动设备上,OverDraw 的压力主要来自半透明物体。因为多数情

况下,半透明物体需要开启 Alpha Blend 且关闭 ZWrite,同时如果我们绘制

像 alpha=0 这种实际上不会产生效果的颜色上去,也同样有 Blend 操作,这是

一种极大的浪费。我们的 UI 绘制是 Alpha Blend 且关闭 ZWrite,因此 UI OverDraw 的优化主要

是在制作界面的时候减少 UI 重叠层级(和策划、美术 pk)。除此之外还是有一

些我们程序可以控制的优化点:1.对于九宫格的 Image,如果去掉 fillcenter 不影响最后出来的效果就要把

fillcenter 去掉,可以减少中间一片的像素绘制;2.看不见的元素且没有逻辑功能要 disable 或者挪出裁剪区域,而不要通过设置Alpha=0 来隐藏;3.不要使用一张 Alpha=0 的 Image 来实现放大响应区域的功能;4.UI 底层系统来控制隐藏看不见的元素,例如打开全屏 UI 的时候把下面看不见的 UI 挪出裁减区域、关闭主相机渲染。

CPU优化

的。优化思路很简单,合批绘制。UGUI 本身的动态合批机制会帮我们尽量的去

优化合批,我们要做的就是弄清楚它的合批机制然后让 UI 元素尽量合批绘制。合理分配图集,同一个界面上的图尽量打到一个图集,多个界面复用的图,放到 common;

以在布局界面的时候也要尽量避免穿插打断绘制流程;

这个位置不是指的 Rectranform 上面的 size 位置重叠就一定打断绘制,而是真

实的三角面的位置是否重叠。这个可以在 Scene 视图下用线框模式(Texture

Wire)去观察;

模版缓存里的东西才是可见的。模板缓存会打断所有的合批,Mask 的子节点和

外面的节点无法合批,模板缓存自己占一个 DrawCall。Unity5.2 之后的版本建

议使用 2D Rect Mask 替代。

Profiler介绍及优化

优化重点

A:CPU-GC Allow:1.检测任何一次性内存分配大于2KB的选项 2.检测每帧都具有20B以上内存分配的选项.

B:Time ms:记录游戏运行时每帧CPU占用(特别注意占用5ms以上的).

C:Memory Profiler-Other:1.ManagedHeap.UsedSize: 移动游戏建议不要超过20MB. 2.SerializedFile: 通过异步加载(LoadFromCache、WWW等)的时候留下的序列化文件,可监视是否被卸载. 3.WebStream: 通过异步WWW下载的资源文件在内存中的解压版本,比SerializedFile大几倍或几十倍,重点监视.

D: Memory Profiler-Assets: 1.Texture2D: 重点检查是否有重复资源和超大Memory是否需要压缩等. 2.AnimationClip: 重点检查是否有重复资源. 3.Mesh: 重点检查是否有重复资源.

E:Device.Present: 1.GPU的presentdevice确实非常耗时,一般出现在使用了非常复杂的shader.2.GPU运行的非常快,而由于Vsync的原因,使得它需要等待较长的时间.3.同样是Vsync的原因,但其他线程非常耗时,所以导致该等待时间很长,比如:过量AssetBundle加载时容易出现该问题.4.Shader.CreateGPUProgram:Shader在runtime阶段(非预加载)会出现卡顿(华为K3V2芯片).

F:StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace(): 1.一般是由Debug.Log或类似API造成. 2.游戏发布后需将Debug API进行屏蔽.

G:GC.Collect: 原因: 1.代码分配内存过量(恶性的) 2.一定时间间隔由系统调用(良性的). 占用时间:1.与现有Garbage size相关 2.与剩余内存使用颗粒相关(比如场景物件过多,利用率低的情况下,GC释放后需要做内存重排)

H:GarbageCollectAssetsProfile:1.引擎在执行UnloadUnusedAssets操作(该操作是比较耗时的,建议在切场景的时候进行). 2.尽可能地避免使用Unity内建GUI,避免GUI.Repaint过渡GC Allow. 3.if(other.tag == GearParent.MogoPlayerTag)改为other.CompareTag(GearParent.MogoPlayerTag).因为other.tag为产生180B的GC Allow.

I:少用foreach,因为每次foreach为产生一个enumerator(约16B的内存分配),尽量改为for. Lambda表达式,使用不当会产生内存泄漏. 尽量少用LINQ:1.部分功能无法在某些平台使用. 2.会分配大量GC Allow.

J:控制StartCoroutine的次数: 1.开启一个Coroutine(协程),至少分配37B的内存. 2.Coroutine类的实例 -- 21B. 3.Enumerator -- 16B.缓存组件: 1.每次GetComponent均会分配一定的GC Allow. 2.每次Object.name都会分配39B的堆内存.

K:1:许多贴图采用的Format格式是ARGB 32 bit所以保真度很高但占用的内存也很大。在不失真的前提下,适当压缩贴图,使用ARGB 16 bit就会减少一倍,如果继续Android采用RGBA Compressed ETC2 8 bits(iOS采用RGBA Compressed PVRTC 4 bits),又可以再减少一倍。把不需要透贴但有alpha通道的贴图,全都转换格式Android:RGB Compressed ETC 4 bits,iOS:RGB Compressed PVRTC 4 bits。2:当加载一个新的Prefab或贴图,不及时回收,它就会永驻在内存中,就算切换场景也不会销毁。应该确定物体不再使用或长时间不使用就先把物体制空(null),然后调用Resources.UnloadUnusedAssets(),才能真正释放内存。3:有大量空白的图集贴图,可以用TexturePacker等工具进行优化或考虑合并到其他图集中。4:要保证每张图得像素宽高都是4得倍数,即除4余0.

L:AudioClip:播放时长较长的音乐文件需要进行压缩成.mp3或.ogg格式,时长较短的音效文件可以使用.wav 或.aiff格式。

M:Setpass call 的数值低,Draw call 不一定低,但是SetPass call 的数值高的话,Draw call 一定高;Batches 的数值一定情况下与Draw call的数值比较接近,这个数值要尽量去优化,尽量多利用Unity 的 Dynamic Batch 功能。动态合批的原理是将所有的顶点转换为CPU的世界空间,如果应用没有调用过图形API,则这个动态批处理不是优势,例如:控制台程序 1)使用相同的Material,使用的阴影也尽量相同,或者不使用阴影; 2)一帧的顶点数不超过900个; 3)Shader使用 Vertex Position, Normal and single UV 可以批量处理300个顶点,Shader使用 Vertex Position, Normal, UV0, UV1 and Tangent,可以批量处理180个顶点; 4)如果相同的GameObject被copy了一份,新得这一份修改了 Scale (放大缩小),则不可以进行动态合批; 5)光照贴图需要在批处理中严丝合缝; 6)Legacy Deferred(光预传递)渲染路径禁用动态批处理,因为它必须绘制两次GameObjects,绘制时调用额外的像素光不会被合批

上一篇下一篇

猜你喜欢

热点阅读