赞
踩
3个方面:
(1)CPU方面
(2)GPU方面
(3)内存方面
CPU方面的优化。
常见的项目:
(1)DrawCalls
(2)物理组件(Physics)
(3)GC
(4)脚本中的代码质量
对DrawCall的优化
DrawCall是CPU调用底层图形接口。对于CPU来说,图形处理的工作量是一样的,所以对DrawCall的优化,主要是为了尽量解放CPU在调用图形接口上的开销。主要思路就是每个物体尽量减少渲染次数,多个物体最好一起渲染。按这个思路有以下3个方案:
(1)使用Draw Call Batching,也就是描绘调用批处理。Unity 3D在运行时可以将一些物体进行合并,从而用一个描绘调用来渲染他们。
(2)通过把纹理打包成图集尽量减少材质的使用。
(3)尽量少的使用反光﹑阴影之类的效果,因为那会使物体多次渲染。
使用Draw Call Batching批处理
保证材质相同,是为了保证被渲染的纹理相同。
Draw Call Batching本身,也还会细分为两种,即Static Batching静态批处理和Dynamic Batching动态批处理。
Static Batching静态批处理
只要这些物体不移动,并且拥有相同的材质,静态批处理就允许引擎对任意大小的集合物体进行批处理来降低描绘调用。
如场景中的山﹑石头﹑建筑等,永远不会移动﹑旋转﹑缩放。只需在Inspector面板中勾选“Static”复选框即可。
Dynamic Batching动态批处理
动态批处理是引擎自动进行的,无须像静态批处理那样手动设置Static。但是存在很多约束:
(1)批处理动态物体需要在每个定点上进行一定的开销,所以动态批处理处理仅支持小于900顶点的网格物体。
(2)如果着色器使用顶点位置﹑法线和UV值3种属性,那么只能批处理300顶点一下的物体;如果着色器需要使用顶点位置﹑法线﹑UV0﹑UV1和切向量,那么只能批处理180顶点一下的物体。
(3)不要使用缩放。分别拥有缩放大小(1,1,1)和(2,2,2)的两个物体将不会进行批处理。
(4)统一缩放的物体不会与非统一缩放的物体进行批处理。
(5)使用缩放尺度(1,1,1)和(1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1)和(1,2,1)的两个物体将可以进行批处理。
(6)使用不同材质的实例化物体(instance)将会导致批处理失败。
(7)使用lightmap的物体含有额外(隐藏)的材质属性,例如lightmap的偏移和缩放系数等。拥有lightmap的物体将不会进行批处理(除非它们指向lightmap的同一部分)。
(8)多通道的shader会妨碍批处理操作。
(9)预制体的实例会自动的使用相同的网格模型和材质。
所以尽量使用静态批处理。
对物理组件的优化
第一点是设置一个合适的Fixed Timestep。它和物理计算有关。所以若计算的频率太高,自然会影响CPU的开销。若是计算频率达不到游戏设计要求,又会影响功能实现。所以具体分析,选择合适的值。
第二点是尽量不要使用网格碰撞器(mesh collider)。mesh collider太过于复杂。
从性能优化角度考虑,物理组件能少用还是少用为好。
GC
GC是用来处理内存的,但的确增加的是CPU的开销。对于GC的优化目标就是尽量少的触发GC。
首先所谓的GC是Mono运行时的机制,所以GC也主要是针对Mono的对象来说的,而它管理也是Mono的托管堆。
其次要清楚什么东西被分配到托管堆上,那就是引用类型。主要是类实例﹑字符串和数组等。
(1)堆的内存不足时,会自动调用GC。
(2)作为编程人员,可以手动调用GC。
不能频繁的触发GC,说白了也就是代码的优化,注意以下5点:
(1)字符串连接的处理。
(2)尽量不要使用foreach语句,而是使用for语句。
(3)不要直接访问gameobject的tag属性。如go.tag == "xxx"换作go.CompareTag("xxx")。访问物体tag会在堆上额外分配空间。
(4)使用“池”技术,以实现空间的重复利用。
(5)最好不要使用LINQ的命令,会分配临时的空间。
对代码质量的优化。
(1)以物体transform组件为例,我们应该只访问一次,之后就将它的引用保留,而非每次使用都去访问。
(2)最好不要频繁使用GetComponent,尤其是在循环中。
(3)善于使用OnBecameVisible()和OnBecameInVisible()来控制物体的update()函数的执行以减少开销。
(4)使用内建的数组,如Vector3.zero而不是new Vector(0,0,0)。
(5)对于方法的参数的优化,善于使用ref关键字。比较复杂的值类型。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
对GPU的优化
GPU的瓶颈主要在一下4个方面:
(1)填充率,可以简单的理解为图形单元每秒的像素数量。
(2)像素的复杂度,比如动态阴影﹑光照﹑复杂的shader等。
(3)几何体的复杂度(顶点数量)。
(4)GPU的显存带宽。
影响GPU性能的无非就是两大方面,一方面是顶点数量过多,像素计算过于复杂;另一方面就是GOU的显存带宽。
针对这两个方面,举措:
(1)减少顶点数量,简化计算复杂度。
(2)压缩图片,以适应显存带宽。
减少绘制的数目也就是减少顶点数量,简化计算复杂度:
(1)保持材质的数目尽可能的少。使得unity更容易进行批处理。
(2)使用纹理图集来代替一系列单独的小贴图。它们可以更快的被加载,具有很少的状态转化,而且批处理更友好。
(3)如果使用了纹理图集和共享材质,使用Render.sharedMaterial来代替Render.material。
(4)使用光照纹理(lightmap)而非实时灯光。
(5)使用LOD,好处就是对那些离得远,看不清的物体的细节可以忽略。
(6)遮挡剔除(Occlusion culling)。
(7)使用mobile版的shader,因为简单。
优化显存带宽就是压缩图片,减小显存带宽的压力。
(1)OpenGL ES 2.0使用ETC1格式压缩等。在打包设置那里有。
(2)使用MipMap。
MipMap主图伴有一系列逐层缩小的备份小图。内存占用会比之前大,但是可以根据实际情况,选择适合的小图来渲染,图片渲染的质量(比压缩要好)。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
内存的优化
unity3d是如何分配内存的。从大的方面可以分为3类:
(1)Unity 3D的内部内存。
(2)Mono的托管内存。
(3)若干我们自己引入的DLL或者第三方DLL所需要的内存。
Unity 3D的内部内存。
(1)资源:纹理﹑网格﹑音频等。
(2)gameobject和各种组件。
(3)引擎内部逻辑需要的内存:渲染器﹑物理系统﹑粒子系统等。
Mono的托管内存。
引用类型分配在堆上涉及GC。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。