本文讲解CocosCreator3.x引擎的资源管理机制,提供一种动态资源的加载和释放方案,在3.3.2版本测试通过。
1 简介
Creator3.x引擎提供了一套基于引用计数的资源释放机制,简单说就是使用时计数加1,不用时计数减1,当计数为0时自动释放。通过引擎加载的资源,都会被临时缓存在 assetManager.assets,以便下次复用。不过这也会造成内存的占用和持续增长,所以有些资源如果不再使用,就可以进行释放。
对于静态引用资源(通过编辑器绑定的资源),引擎会自动统计引用计数并在计数为0时自动释放。
对于动态引用资源(通过代码加载的资源,例如:resources目录和远程资源),受限于JavaScript的动态语言特性,引擎很难跟踪资源的使用情况,所以需要开发者自己进行管理并正确释放。
2 资源释放机制
以使用最广泛的资源图片为例,引擎每加载一张新的图片,都会在内存中为3种对象各创建一个实例,分别是 SpriteFrame、Texture2D、ImageAsset。在动态合图开启的情况下,这3个实例自动记录到缓存 assetManager.assets._map 中;如果动态合图关闭,则只添加 SpriteFrame 和 Texture2D,但 ImageAsset 实际上仍然存在内存中,只是不在缓存列表中而已。其中,SpriteFrame 依赖于 Texture2D,Texture2D 依赖于 ImageAsset,它们之间关系如下图所示:
我们要做的资源释放,主要就是释放 SpriteFrame、Texture2D、ImageAsset 这三种对象。其中 Texture2D 保存着真正的纹理信息,释放 Texture2D 会把纹理从GPU
中删除,也就是真正释放内存。
本文主要讲解动态引用资源,即resources
和远程资源
的释放。在此之前,先看下引擎是怎么管理和释放静态资源的。
2.1 静态资源的计数和释放
假设a、b、c三个节点都绑定了 x 图片资源,则 x 资源的引用计数情况如下:
节点 | SpriteFrame | Texture2D | ImageAsset |
a加载后 | 1 | 1 | 1 |
b加载后 | 2 | 1 | 1 |
c加载后 | 3 | 1 | 1 |
可以看到,虽然有多个节点,但 SpriteFrame、Texture2D 和 ImageAsset 实例始终只有一份,只是递增了SpriteFrame
的引用计数,而Texture2D
和ImageAsset
的引用计数则始终是1,因为它们只被一个SpriteFrame
所引用。
如果设置了场景的“自动释放”选项,则场景切换时,如果a、b、c三个节点都被释放,则 SpriteFrame 中的计数依次减1,当减到0时,就会走真正的资源释放了,分以下几步:
• 1)首先把自己从缓存列表中删除;
• 2)遍历其依赖资源,