效率相关笔记

简要清单,让你的游戏速度更快:
(1)保持顶点数如下:针对iPhone 3GS和更加新的设备(带SGX GPU),每帧40K;针对旧设备(带MBX GPU)每帧10K。
(2)物体之间尽可能共享相同的材质,这样有利于进行渲染合批,对于不同贴图同一材质的,可以将多张贴图合成一张,只合并两个物体而没有共享材质,这样不会给你带来任何性能提高。
  每场景中不同的材质的数量尽可能少。
  相同相机,如果被渲染的物体使用相同的材质, Unity IOS能够运用多种内部优化。额外的工作放在合并纹理成单一的图集的和让物体使用相同的材质,总会有回报的。做到这一点!
(3)非移动的物体上设置静态Static 属性,这样可以进行内部优化。
(4)在可能的情况下使用ETC1格式的纹理,否则,选择16bit纹理优于32bit未压缩的纹理数据。
(5)当没有必要时,不要使用像素灯- 选择只有一个(最好是方向光)像素灯的光线影响您的几何图形
  当没有必要时,不要使用动态光源- 选择烘焙照明
  逐像素的动态照明将显着增加每个受影响的像素的渲染开销,并可能导致对象多次渲染。避免多于一个像素灯 Pixel Light照亮任何单一的物件,并尽量使用方向灯。请注意,一个像素灯,渲染模式选项设置为重要Important。
  逐顶点的动态照明显着增加顶点转变的开销。尽量避免多个灯照亮任何给定的物体的情况,对于静态对象,烘焙照明更加高效。
(6)避免使用alpha测试,而是选择alpha混合。
(7)当没有必要时,不要使用雾效。
(8)了解遮挡剔除的好处,在复杂的静态场景的情况下,有很多遮挡,用它来减少可见几何体的数量和绘制调用。计划你的关卡,受益于遮挡剔除。
(9)使用天空盒制造出"假"遥远的几何体
(10)Per-Layer Cull Distances 每层消隐距离
  使用Camera.layerCullDistances函数,设置每一层消隐距离。这样可以把远距离的需需要渲染的物体隐掉,以减少渲染批次。

(11)Texture的Read/Write Enable选项:选择此项将允许从脚本(GetPixels,SetPixels和其他Texture2D函数)访问纹理数据。但是注意,一个纹理数据副本将产生,由此必将为纹理资源消耗双倍的内存量。只有在绝对必要时使用。默认情况下禁用。

着色器相关:
(1)使用合并器或像素着色器,混合每帧的多个纹理,而不是用多通道方法
(2)如果您使用的是内置的着色器,对于移动平台。记住,Mobile / VertexLit 是目前最快的着色器。
(3)如果编写自定义的着色器,用尽可能小的浮点格式
  fixed / lowp -- perfect for color, lighting information and normals,
  用于颜色,灯光信息和法线
  half / mediump -- for texture UV coordinates,
  用于纹理UV坐标,
  float / highp -- avoid in pixel shaders, fine to use in vertex shader for vertex position calculations.
  尽可能地使用最低的精度,这点对于iOS和Android平台特别重要。推荐的经验法则:对于颜色和单位长度的向量,使用fixed;对于其他的,如果范围和精度允许的话,使用half,否则使用float。
  在移动平台上,关键是在片段着色器中使用尽可能多低精度数据计算。在大多数移动设备的GPU中,在低精度 (fixed/lowp) 类型上应用swizzles是比较耗时的;同时,在fixed/lowp 和高精度类型之间进行转换也是需要付出很大代价的。
(4)尽量减少在像素着色器使用复杂的数学运算,如pow, sin, cos 等。
(5)每个fragment使用较少的纹理。
(6)通常地说,所需要渲染的像素(像素着色器执行)个数要比所需要渲染的顶点(顶点着色器执行)个数要多,同时,所需要渲染的顶点个数也要比模型的个数要多。所以,一般来说,尽可能地将计算量从像素着色器移到顶点着色器中,或者完全从着色器中移除并从
  脚本中来赋值。避免在像素着色器,而是使用顶点着色器,计算顶点的位置。

批处理相关:
DrawCall: 引擎准备好数据并通知GPU绘制的过程称为一次DrawCall。一般一个物体一个Draw Call
  每帧的DrawCall数是一项非常重要的指标,不只是GPU渲染,引擎重设材质/Shader也是非常耗时的操作。
Draw Call Batching技术:
  Unity内置的合并处理技术,优点:将相同变换、材质的物体组合成一个物体进行一次Draw Call;缺点:组合成的物体会成为一个新的物体,耗费内存和CPU。
  Dynamic Batching:自动进行不需要手动干预,对于顶点数在300以内的可移动物体,只要使用相同的材质,就会组成Batch。
  Static Batching:收费的,static对象无论大小都会batch。
  要有效利用Draw Call Batching,首先是尽量减少场景中使用的材质数量,即尽量共享材质,对于仅纹理不同的材质可以把纹理组合到一张更大的纹理中(称为Texture Atlasing)。然后是把不会移动的物体标记为Static。

Android:

(1)更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,每家的GPU支持不同的压缩格式,但他们都兼容ETC格式。
(2)对于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。
(3)减少FPS,在ProjectSetting-> Quality中的VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
  这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)降低FPS的好处: 1)省电,减少手机发热的情况;2)能都稳定游戏FPS,减少出现卡顿的情况。
(4)当我们设置了FPS后,再调整下Fixed timestep这个参数,这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来提高游戏性能。
(5)尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。
(6)待机时,调整游戏的FPS为1,节省电量。
(7)每个“foreach”循环的每次迭代会生成24字节的垃圾内存。一个简单的循环迭代10次就可以留下240字节的垃圾内存。
  不使用LINQ命令,因为它们一般会分配中间缓器,而这很容易生成垃圾内存。

 IOS:

(1)尽可能地选择PVRTC格式的纹理,如果不能地话,也请选择16位纹理而不是32位的。
(2)使用合并或像素着色器来混合每个片段的纹理,来代替多通道渲染方法。
(3)尽量不要使用雾效果。

Profiler内存值分析:
(1)Used Total和Reserved 均是物理内存,其中Reserved是unity向系统申请的总内存,Unity底层为了不经常向系统申请开辟内存,开启了较大一块内存作为缓存,即所谓的Reserved内存,而运行时,unity所使用的内存首先是向Reserved中来申请内存,当不使用时也是先向Reserved中释放内存,从而来保证游戏运行的流畅性。
一般来说,我们均建议尽可能地控制Used Total的大小,Used Total越大,则Reserved Total越大,而当Used Total降下去后,Reserved Total也是会随之下降的(但并不一定与Used Total同步)。
(2)通过PSS来查看移动端的内存是相当不准确的。Profiler记录的是通过引擎分配的真实物理内存,而PSS中多出的内存大致分为两部分,一部分是App在运行会调用底层的一些核心库,这些库都会占用一定的内存;第二部分则是移动系统决定的,即虽然游戏中已经将资源卸载掉,但在系统层面上,系统并不会及时将其清除,而是将其缓存住,这样做的处理是为了便于以后该资源的复用效率,同时,当系统的内存分配达到上限时,系统本身会调用内存清理机制来轮询这些缓存区域,进而释放内存。
(3)ManagedHeap的内存值是由所写的C#代码来引起并造成的,建议时刻关注CPU Profiler中的GC Collcet值,查看由哪些选项分配较大或不断分配GC Allocation。这个是造成ManagedHeap不断增大的原因。
(4)GfxDriver可以理解为GPU显存开销,主要由Texture,Vertex buffer以及index buffer组成。所以尽可能地减少或释放Texture和mesh等资源,即可降低GfxDriver内存。

贴图优化:
(1)在使用OpenGL ES2.0的Android上,仅支持ETC1,该格式不支持透明通道,于是可以将一张texture拆分成RGB24的和一张Alpha8的贴图,然后分别使用ETC1压缩。
(2)Mipmap可以降低渲染带宽压力,但会导致内存变为1.33倍,3D场景和角色建议开启;UI渲染在屏幕最上层,开启了mipmap并不会提升渲染效率,不建议开启。
(3)Read&Write会导致纹理内存增大一倍。
(4)网格里面的Normal Color Tangent数据能不用就不用,在合批的时候,一个模型带有此类数据,会导致其他的模型也自动添加该数据。

托管堆:
概念:由Mono分配和管理、自动调用gc、
问题:Mono堆一旦分配就不会返还给系统、只增不降
经验:
  不要在update中new class/container/array,累计开销非常大
  严格控制Log输出
  UIPanel.LateUpdate的CPU和堆内存开销很大

和Assetbundle包相关的内存:
(1)WebStream:AssetBundle原始文件大小 + 解压后的数据大小 + DecompressionBuffer(0.5M)
      new WWW(url)方式下载bundle
(2)SerializedFile:解压后的AssetBundle存于本地,通过本地磁盘空间来换取内存空间
      LoadFromCacheOrDownload
      CreateFromFile
      new WWW(本地文件)

 

 

上一篇:vue网页端web聊天IM实例|仿微信客户端vue版


下一篇:zabbix性能优化实践