CocosCreator客户端优化系列(三):内存优化

本文链接:https://blog.csdn.net/zzx023/article/details/88822815
CocosCreator客户端优化系列(三):内存优化

    转载请保留原文链接:https://blog.csdn.net/zzx023/article/details/88822815

静态资源的内存管理

可以参考官方文档:管理场景

静态资源指的是场景中直接或间接引用到的所有资源(脚本动态加载的资源不算在内)

在场景资源的属性编辑器中可以勾选“自动释放资源”选项,从而在切换场景时,会自动将旧场景使用的静态资源释放掉,从而节省内存的占用
在这里插入图片描述
动态资源的内存管理

    动态资源的加载

动态资源统一使用cc.loader进行资源的加载以及管理。
参考:动态加载
可以使用的api:

cc.loader.load
cc.loader.loadRes
cc.loader.loadResArray
cc.loader.loadResDir

    1
    2
    3
    4

详细的api使用参考[官方文档],这里就不细说了(https://docs.cocos.com/creator/api/zh/classes/loader.html#load)

要注意的一点是,CocosCreator中通过cc.loader去加载资源的所有方法,都是异步的
所以需要在回调中,确认加载完成后才能使用资源。

也可以通过

cc.loader.getRes

    1

这个api去同步的获取资源,但需要对get到的资源进行检查,如果没有加载或者没有加载完成,则需要等待或者通过cc.loader进行加载。
这样的话整个代码会清晰一些,避免掉入js的回调地狱中
例如:
在这里插入图片描述
通过简单的封装两个方法,在使用时可以保持代码的整洁易读

另外一点需要注意的是,当批量进行加载时,cc.loader也提供了onProgress回调,这个回调中的三个参数中
在这里插入图片描述
totalCount并不是指的是加载的资源总个数,而是加载这个资源所需要加载的依赖项个数。
比如加载一个SpriteFrame,它的totalCount就是3,这3个item分别为:json,texture2D和SpriteFrame
所以当totalCount为0时,并不是代表加载资源总个数为0,而是意味着这些资源已经加载过在内存中了,可以直接使用。

    动态资源的释放
    动态资源的释放同样时通过cc.loader去管理的。
    有两种释放资源的管理方式:
    (1)自动释放资源
    我们可以通过

    cc.loader.setAutoRelease
    cc.loader.setAutoReleaseRecursively
        1
        2

    来管理资源的自动释放设置
    在这里插入图片描述

    当场景切换时,由于资源已经释放,脚本中如果保留了引用,此时该引用将会变为非法引用。可以使用setAutoRelease和setAutoReleaseRecursively来保留这些资源。

    setAutoReleaseRecursively指定资源及资源递归引用到的所有资源

    默认情况下,当加载新场景时,旧场景的资源根据旧场景是否勾选“Auto Release Assets”,将会被释放或者保留。 而使用 cc.loader.loadRes 或 cc.loader.loadResDir 动态加载的资源,则不受场景设置的影响,默认不自动释放。
    使用这个 API 可以在单个资源上改变这个默认行为,强制在切换场景时保留或者释放指定资源。

    (2)手动释放资源
    cc.loader提供了以下的api,都可以去释放通过cc.loader加载进来的资源内存。

    cc.loader.release
    cc.loader.releaseRes
    cc.loader.releaseAsset
    cc.loader.releaseAll
        1
        2
        3
        4

    这里常用的时cc.loader.release

    不推荐使用cc.loader.releaseAll
    因为cc.loader.releaseAll会将所有通过cc.loader加载进来的动态资源全部释放掉,而在我们正常的项目开发过程中,基本上很少有场景没有使用到动态资源的情况,所以这种释放通常会带来程序的崩溃,因此使用上不推荐,最好不要使用。

    cc.loader.release在释放资源时注意配合

    cc.loader.getDependsRecursively
        1

    使用。

    例如在release一个prefab资源时,如果只是通过

    cc.loader.release(this.prefab);
        1

    的话,这样只会release掉这个prefab所使用的json文件,而prefab所引用的spriteFrame以及其他的一些资源并不会释放掉,这样就有可能会造成内存的垃圾,长时间占用内存

    配合getDependsRecursively就可以正确的销毁掉prefab
    在这里插入图片描述

    在销毁prefab时也可以配合自动释放资源功能,将一些特殊资源保留在内存中,避免重复加载
    在这里插入图片描述

如何找到“垃圾”

随着游戏的运行,总会有一些内存是长时间不使用,同时又因为我们疏忽从而造成内存上的占用以及浪费。
通过google提供的snapshot以及Allocation Profile工具可以帮助我们找到这些垃圾
在这里插入图片描述
查找内存“垃圾”过程中需要注意的是:

    注意简单的对象创建,例如数组,{}
    注意不要忽略匿名函数
    注意匿名函数使用的外部变量将被匿名函数持有
    利用Timeline 观察 GC 调用频率
    寻找长期不释放的蓝色内存

复用一切可复用的对象

最后是内存使用的一个理念:复用一切可复用的对象

复用,并不仅仅是为了节省对象在alloc造成的开销,更重要的是避免GC时带来的额外开销。

像一些战斗中的掉血数字,敌人的血槽,怪物,子弹,英雄头像等等,都是我们常常回去做复用的地方。

但还有一些地方我们不能忽略,比如:
基础对象:cc.v2,cc.color 等
数组和对象 {}

对于常见一些复杂对象,我们可以使用对象池NodePool进行复用
对于基础的对象我们可以直接进行赋值从而达到复用的目的
参考引擎源码:
在这里插入图片描述
只有在不穿入out的时候new新的对象出来,正常情况下的使用均是在原有的out上进行复用

var v1;
v.add(cc.v2(5, 5), v1);
//to do....
v.add(cc.v2(10, 10), v1);
//to do....

需要注意的是:注意闭包,注意复用时避免泄漏为全局变量
 ————————————————
版权声明:本文为CSDN博主「BigBear023」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zzx023/article/details/88822815

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值