读一读

对于频繁分配小块内存的可以在固定帧数的时候主动调用GC回收。

对于内存分配不频繁的且可以在暂停时才回收的,可以在启动时使用空物体等来扩大堆空间,来扩充到游戏暂停前(GC回收垃圾)空闲的堆空间不被填满。然后在暂停的时机调用GC回收。

具体优化情况,参考profiler的统计数据。


在经常调用的函数或则是帧函数中要减少临时变量的使用,例如一个函数需要返回一个数组,而这个函数需要经常调用时,函数里面会经常的为临时的数组分配内存,下一秒又不用了,产生了大量垃圾,增加GC的负担。所以,对于这类型的应该使用一个全局的变量来通过参数的形式来传入引用,然后修改对应的值来再返回。


内存管理器会在空闲堆空间不够用时去检测没有被引用的内存,然后去回收,然而,当这些垃圾数量很多的时候就会造成回收耗费大量资源从而影响游戏的性能。所以,有一个办法就是保证内存中的垃圾不要过多,我们可以定时的、在合适的时机去主动调用GC去回收。

if (Time.frameCount % 60 == 0) {
    System.GC.Collect();
}

对于那些复杂点的,但是又不需要每一帧都去执行的代码,我们可以使用InvokeRepeating来指定每秒调用方法的次数,从而节省性能。

void Start () {
    InvokeRepeating("Repeat", 0, 0.2f);
}

int a;
void Repeat() {
    for (int i = 0; i < 10000000; i++)
        a = i * i;
}

经过测试,如果在Update中去大量的(10W次)去寻找GameObject或获得组件,帧率会有大幅度的下降,特别时Find等的操作方法。在Update中执行普通的运算10W次基本上不影响帧率,所以说Find和GetComponent等方法的执行时具有一定的耗时的,所以最好就是将这些放到Start中,通过引用把查找获取的结果保存下来。

private GameObject cube;
void Start () {
    cube = GameObject.Find("Cube");
}

当我们要为一个Label每帧都赋值一个string时,就会产生垃圾,引起GC的回收,影响性能和分析不正确。

可以使用一个固定的数组列举所有的情况,用内存来减少垃圾生成从而调用GC


打开profiler分析游戏性能,如果开启了垂直同步vsync,它会主导profiler的Cpu图形。应打开Edit/Project Settings/Quality调整

在profiler中可以看到CPU图形上老是有突起出现,这些是因为Editor的关系,当你去选择一些东西的时候会导致调用CameView.GetMainGameViewRenderRect

我们可以导出.exe,设置DevelopmentBuild和Autoconnect Profile,运行后,Unity将自动捕捉分析数据。


使用图片压缩,图片的格式对大小影响不大,使用mipmap将会3倍大小。代码能不用System就不用,这会加大数M包的大小。使用a subset .Net2.0,如果可以。


模型大小最好在制作时做成对应大小,或者导入时设置好比例,使用scale调节比例会降低性能。