前言:
我做了3年的Unity了,但是却没有深入优化模块的内容,只能怪自己做项目的时候做的内容太杂乱了。去面试的时候被面试官问道优化方面的内容的时候自己一脸懵逼。本来有机会去MK的,让自己错失了。 所以自己将优化的内容做一个小小的总结,后续再做细化的研究。
正文:
根据性能指标设定优化目标
游戏的性能指标有:帧率,稳定性(卡顿),等待时间(Loading),内存占用(手机上最重要指标,绝大部分闪退的原因,理想值是内存占用低于150M),安装包大小,网络延迟,网络流量,耗电量(手机比较重要,限帧)等等。
根据性能指标设定优化目标
一般来说游戏优化也遵循28原则,游戏优化又是很费时费力的一件事,我们需要找出性能瓶颈。按照优先级来进行优化。
望闻:根据优化目标,先大概分析一下性能指标。包括帧数多少,是否稳定,是否存在卡顿。较长时间运行,发热量如何,是否存在闪退。安装包多大。网络流量多大等。找到最优先需要解决的点。
问:询问相关开发人员性能热点大概从什么时候开始出现。我们之前的项目在开发到中后期会找测试同学测试每日构建的版本,及时监控性能指标,第一时间发现性能瓶颈,发现越早越容易优化。
切:通过一些工具分析来进行深度的分析,必要时需要自己开发分析工具,定位热点。
优化工具
https://mp.csdn.net/mdeditor/88038813#
Unity需要优化的前提是安装包过大或者运行时候卡。
需要进行优化的地方有:
1.渲染优化
1.CPU GPU分工
2.LOD层级细节
3.Occlusion Culling-遮挡踢出
4.Lightmapping-光照贴图
5.合并Mesh
6.Gpu Instance
7.FPS优化
2.代码优化
3.资源优化
1.资源优化的标准
2.模型优化
3.贴图优化
4.如何减少冗余资源和重复资源
5.资源的检测和分析
6.合并材质球
4.DrawCall优化
一、渲染优化
1.CPU和GPU的分工
CPU是负责游戏逻辑的,GPU是负责显示特效
2.LOD - 层级细节
LOD 即 Levels of Detail 的简称 , 意为多细节层次 . LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度 , 可根据距离动态地选择渲染不同细节的模型 , 决定物体渲染的资源分配 ,
从而获得高效率的渲染运算 . 是最常用的游戏优化技术 .
优点 : 降低非重要物体的面数和细节度,从而获得高效率的渲染运算 .
缺点 : 加重美工的负担 , 要准备不同细节的同一模型 . 会稍微增加游戏的容量 .
3.Occlusion Culling-遮挡踢出
http://blog.csdn.net/cartzhang/article/details/52684127
4.Lightmapping-光照贴图
https://www.cnblogs.com/tgycoder/p/4853534.html
5.合并Mesh
http://blog.csdn.net/chenggong2dm/article/details/41699029
Mesh Baker
1.静态合并
手动勾选为Static,所有被勾选了“Static”的GameObject,其中的Mesh Filter中的mesh都会被合并到 "Combined Mesha (root: scene)" 中。
2.动态合并
using UnityEngine;
using System.Collections;
public class MyClass : MonoBehaviour
{
void Start ()
{
MeshFilter [] meshFilters = GetComponentsInChildren<MeshFilter> ();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
for (int i = 0; i < meshFilters.Length; i++) {
combine [i].mesh = meshFilters [i].sharedMesh;
combine [i].transform = meshFilters [i].transform.localToWorldMatrix;
meshFilters [i].gameObject.active = false;
}
transform.GetComponent<MeshFilter> ().mesh = new Mesh ();
transform.GetComponent<MeshFilter> ().mesh.CombineMeshes (combine);
transform.gameObject.active = true;
}
}
- 先在 Unity 中建立 空物件 ( Empty )
- 再创建2个 Cube 方块,并放入 空物件底下 (可以改成你自己的模型)
- 把 MyClass 代码丟进 空物件上 。
- (可选) 建立一个 Material 材质,并且丢进 空物件上
- 执行
6.Gpu Instance
Gpu Instance是一种用来提高渲染大量物体效率的技术,随着手游游戏品质需求的提升,我需要在场景里绘制越来越多的物体,这里面主要涉及 两个方面的性能 瓶颈,一是cpu对gpu提交数据的次数(包括设置数据buffer,渲染状态以及调用对渲染原语的绘制即drawcall),二是gpu上的绘制(包括顶点处理和像素绘制),随着场景物体的提升,cpu和gpu的压力都会上升。目前在一些典型的3D游戏的制作中,我们的经验值是全屏不超过10万个顶点和200个draw call左右,不然对中端机器会有一定压力。
为了解决场景绘制效率这个问题,主要有以下几种优化方案:
static batching: 即静态合批,静态合批的原理即化整为零,将多个场景物体预先合成一个大的物体进行绘制,unity5的实现就是整合成一个大的vbo,而不整合IBO,一次性提交vbo给gpu,然后并不是把整个vbo都绘制,而是每次需要绘制其中某个某些物体时改变IBO,选择大vbo上的某一段进行绘制。静态合批可以将多个小物体的绘制合并成一个大物体的绘制,减少对渲染状态的改变,它一次并行绘制多个物体,理论上是最快的绘制方法,不过最大的缺点是因为合成新的大vbo需要耗费额外的大量内存,同时不能渲染动态物体,因为合并vbo的时候已经确定顶点数据了,顶点数据不能更改(例如unity5对LOD合批的实现也是讲所有层次的lod都预先合并进去),另外一个vbo的大小是有限制的,如果物体数量过多,也会被拆成多个绘制。
dynamic batching:动态合批,可以解决对顶点数据有变化的物体的合批,它动态的合并vbo进行提交,组建vbo的时间有消耗,为了减少这个消耗,unity对动态合批的vbo大小有限制,以致于很小顶点数的物体才有可能被动态合批。