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....
1
2
3
4
5
需要注意的是:注意闭包,注意复用时避免泄漏为全局变量


--------------------- 
作者:BigBear023 
来源:CSDN 
原文:https://blog.csdn.net/zzx023/article/details/88822815 
版权声明:本文为博主原创文章,转载请附上博文链接!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值