优化,老生常谈。游戏的优化和网站、软件优化没有任何不同,除了编码质量和使用技巧以外,都是那些空间<>时间、效果<>性能的老套路。
Debug工具介绍
内存优化
【适当的GC(Garbage Collection垃圾回收)】
GC有两种触发方式,1内存不足自动触发,2手动触发。
首先内存不足时自动GC,经反复测试,并不是很好的办法。因为当内存不足时cpu压力也比较大,在GC之前就已经会发生卡顿现象,GC时还会发生更严重的卡顿。最好的办法还是手动GC。但一定要设计好触发条件。因为过于频繁的GC也很影响性能。
函数相关的优化
【使用for循环,减少foreach】
foreach会涉及到迭代器的使用,而据传每次循环所产生的迭代器会带来24 Bytes的垃圾。
【不直接访问gameobject的tag属性】
比如if (object.tag == “target”)最好换成if (object.CompareTag (“target”))。因为访问物体的tag属性会在堆上额外的分配空间。
【使用对象池,实现对象的复用】
将场景中的对象放在池中调用,节省反复实例化的开销
*【减少GetComponent方法调用组件】
脚本中三种调用Transform组件的方式,其响应时间有着巨大的不同,按时间的相应毫秒数大小排列的话是这个样子:GetComponen > transform= 60ms >myTransformCache
所以应该建立组件的引用留作复用,而不是每次都使用GetComponent。
*【只运行物体在摄像机视野内的脚本】
使用void OnBecameVisible()和void OnBecameVisible()减少摄像机事业外脚本运行的开销。这两个函数分别是 当前物体在摄像机范围内或离开摄像机范围触发。
【尽量使用内建值,减少new的开销】
使用数组内建值,比如Vector3.zero而不是new Vector(0, 0, 0)。
【位置、旋转、缩放的数值要使用低精度】
设置位置旋转和缩放的时,不要使用高精度的变换。否则会产生模型抖动的问题。
贴图、材质优化
【纹理尺寸最好2的整数幕】
【使用纹理图集】
类似前端的雪碧图。用一张包含了很多子贴图的大贴图,来代替一系列单独的小贴图。可以提高加载效率,并且更易于批量处理。
需要使用Renderer.sharedMaterial 代替Renderer.material
【减少透明物体的使用】
由于透明没有开启深度写入所以会造成overdraw。
【使用共享材质】
共享材质可以减少材质数量,便于批量处理。
需要使用Renderer.sharedMaterial 代替Renderer.material
【压缩纹理】
unity统合了纹理压缩的方法。只需按质量等级选择好即可。不过越高的压缩质量,画质越不好。GUI最好不要压缩,质量影响很明显。
【用法&步骤】
点击贴图文件 -> Inspector -> Default -> Compression 选择压缩质量
*【使用多级渐远纹理MipMap】
类似模型LOD技术,逐级生成多个低精度贴图,在适当的情况使用适当的贴图。缺点是会增加内存占用,典型的空间换时间优化。
【操作步骤】
点击贴图文件 -> Generate Mip Map -> Apply。
这时点击Sprite Editor打开窗口,拖拽右上角的拉杆就能看到结果了。
光照优化
*【减少实时光照,使用光照纹理烘焙,或灯光探针】
如果物体使用了多个Pass 的Shader,使用实时光照很有可能会造成性能下降。这是因为实时光照会产生更多的计算量,而且还无法使用动态批处理和静态批处理。
1 使用光照纹理烘焙技术(GI、bake),把光照提前烘焙到一张光照纹理(lightmap ),运行时映射相应的纹理实现光照效果 。这样不仅性能更好而且效果也更好。但缺点是物体必须设置为静态。对于需要移动的物体来说就不太合适。
2 这个时候使用灯光探针(Light Probe Group)是比较好的办法
3如果一定要使用更多的实时光,也可以选择用逐顶点光照来代替。
【减少实时阴影】
使用烘焙把静态物体的阴影信息存储到光照纹理中,只对动态物体使用适当的实时阴影。
模型优化
【尽可能移除隐藏的面】
这会减少顶点和三角面的处理。比如我们的相机在阳台,附近高楼林立。那么实际上只有前面几个楼需要前、左、右的面。远处的楼是不需要左或、右的面。因为看不到。
【合并mesh】
【减少顶点】
建模时应尽量减少模型的顶点。根据动态、静态批处理的触发相关规则,简单着色器模型顶点数必须小于900。如果着色器同时使用顶点位置、法线、UV值三种属性则模型顶点数必须小于300。如果着色器同时使用顶点位置、法线、UV0、UV1、切向量五种属性则模型顶点数必须小于180。
*【减少模型缩放(Scale)】
模型缩放会导致创建新的Batch。不利于动态、静态批处理
【不使用mesh collider】
尽量使用cube collider 等内置colliser。性能会提高很多
*【使用模型的LOD (Level ofDetail )】
使用模型的多级细节技术,在不同的距离使用不同精度的模型、材质。提升cpu、gpu型能,加重内存负担。典型的空间换时间优化技术。
*【使用遮挡剔除( Occlusion Culling )】
*【使用动态批处理(Baches,Saved by batching)】
【使用条件&步骤】
- 场景中存在多个相同模型。如果不是多个相同模型,则批处理无意义。
- 模型顶点数必须小于900。
- 如果着色器同时使用顶点位置、法线、UV值三种属性则模型顶点数必须小于300。如果着色器同时使用顶点位置、法线、UV0、UV1、切向量五种属性则模型顶点数必须小于180。
- 不能进行缩放 Scale。每次调整模型的大小都会产生新的Batch。
- 不能修改材质。每次修改材质都会缠身新的Batch。
- 不能使用lightmap(烘焙光照贴图),除非是先烘焙,后实例化物体。
- 多通道的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道
*【使用静态批处理】
【使用条件&步骤】
点击目标物体,在Inspector窗口勾选Static。
要注意静态批处理不允许改变位置
shader相关优化
【内置shader使用mobile中的】
相比较其他内置shader,mobile性能更好
【尽量把计算放在对象或逐顶点着色器中】
优化对象数量 > 顶点运算 > 像素运算。
尽量不要把运算拖在片源元色器中计算。
【使用更低精度的值类型进行运算】
1 float 计算速度最慢,适合存储顶点坐标,在顶点着色器中使用。
2 half 计算速度快些,适用纹理坐标等变量。
3 fixed 计算速度最快,适用于颜色变量和归一化后的方向矢量,适合在片元着色器中使用。
【使用shader的lod技术】
与模型的 LOD 技术类似, Shader的LOD技术可以根据条件启用shader片段,当Shader 的 LOD 值满足条件设才会渲染。
【根据硬件性能和平台,调整效果方案】
根据不同的硬件性能,选择性的启用特效。
【尽量不要关闭深度测试】
由于被遮挡的物体无法通过深度测试,就不会再进行后面的渲染处理。
*【控制绘制顺序队列】
从前往后绘制,比从后往前绘制性能好的多。这是因为深度测试的存在减少了被遮挡部分的绘制。
【从前往后绘制的队列 - 不透明物体(Opaque)】
Shader中渲染队列值小于2500的对象都被认为是不透明(Opaque)的物体。如“Background"、“Geometry”、“Alpha Test”。
【从后往前绘制的队列 - 透明物体(Transparent)】
Shader中渲染队列值大于2500的对象都被认为是透明(Transparent)物体。如"Transparent"、"Overlay"等
尽可能地把物体的染队列值设置大于2500从而实现从前向后的渲染提升性能。
其他优化
【打包压缩】
Build settings -> compression Method中设置压缩
*【摄像机视锥剔除( Occlusion culling)】
剔除掉那些不在摄像机的视野范围内的对象,从而避免不必要的计算。
【用法&步骤】
点击摄像机 -> Inspector窗口 -> Camera组件 -> 勾选Occlusion Culling。
*【遮挡剔除技术( Occlusion culling)】
剔除掉那些被其他物体遮挡的看不到的物体,从而提升性能。
【用法&步骤】
unity工具栏 -> Windows -> Rending -> Occlusion culling -> Occlusion窗口 -> 作相关设置 -> Bake
后期效果优化插件Process
指定特效作用范围,不要设置ervay thing。这是因为比如GUI之类的东西没有必要被计算。
【gui和场景使用不同的摄像机渲染】
GUI由于其特殊性大多需要设置成透明。如果GUI与场景物体一同西汉时,并且屏幕占比太多,就会造成很多不必要的overdraw。
可以用两个相机分别渲染ui和场景。
*【减小分辨率】
降低屏幕分辨率是 非常有效 的性能优化手段。尤其对于大屏幕低配置的设备。这时可以使用等比例缩小屏幕分辨率的方法来适当优化。用部分效果来换取性能山的提升
【用法&步骤】
///这里作等比例运算,适配过长或过宽的设备
{
//获取当前分辨率
int width = Screen.currentResolution.width;
int height = Screen.currentResolution.height;
}
///
//设置当前分辨率
Screen.SetResolution(640, 480,true);
转载:https://blog.csdn.net/lengyoumo/article/details/105654499