Cocos
编者按
本文来自 Cocos 中文社区,作者宝爷。
资/源/管/理
如果你想使用Cocos Creator制作一些规模稍大的游戏,那么资源管理是必须解决的问题。
但之前使用过的大部分资源都会留在内存中!
为什么会这样呢?
Cocos Creator 资源管理存在的问题
资源管理主要解决 3 个问题,资源加载,资源查找(使用),资源释放。
这里要讨论的主要是资源释放的问题,这个问题看上去非常简单,在 Cocos2d-x 中确实也很简单,但在 js 中变得复杂了起来,因为难以跟踪一个资源是否可以被释放。
在 Cocos2d-x 中我们使用引用计数,在引用计数为 0 的时候释放资源,维护好引用计数即可,而且在 Cocos2d-x 中我们对资源的管理是比较分散的,引擎层面只提供如 TextureCache 、 AudioManager 之类的单例来管理某种特定的资源,大多数的资源都需要我们自己去管理。
而在 Cocos Creator 中,我们的资源统一由 cc.loader 来管理,大量使用 prefab , prefab 与各种资源复杂的引用关系增加了资源管理的难度。
01
资源依赖
资源 A 可能依赖资源 B 、 C 、 D ,而资源 D 又依赖资源 E ,这是非常常见的一种资源依赖情况。
这种方式虽然可以将资源释放,但却有可能释放了不应该释放的资源。
如果有一个资源 F 依赖 D ,这时候就会导致 F 资源无法正常工作。由于 Cocos Creator 引擎没有维护好资源的依赖,导致我们在释放 D 的时候并不知道还有 F 依赖我们。
即使没有 F 依赖,我们也不确定是否可以释放 D ,比如我们调用 cc.loader 加载 D ,而后又加载了 A ,此时 D 已经加载完成, A 可以直接使用。
但如果释放 A 的时候,将 D 也释放了,这就不符合我们的预期。
我们期望的是在我们没有显式地释放 D 时, D 不应该随着其它资源的释放而自动释放。
02
资源使用
除了资源依赖的问题,我们还需要解决资源使用的问题。前者是 cc.loader 内部的资源组织问题,后者是应用层逻辑的资源使用问题。
比如我们需要在一个界面关闭的时候释放某资源,同样会面临一个该不该释放的问题,比如另外一个未关闭的界面是否使用了该资源?
如果有其他地方用到了该资源,那么就不应该释放它!
03
ResLoader
在这里我设计了一个 ResLoader ,来解决 cc.loader 没有解决好的问题。
关键是为每一个资源创建一个 CacheInfo 来记录资源的依赖和使用等信息,以此来判断资源是否可以释放。
对于使用,提供了一个 use 参数,通过该参数来区别是哪里使用了该资源,以及是否有其他地方使用了该资源。
当一个资源即没有被其他资源依赖,也没有被其它逻辑使用,那么这个资源就可以被释放。
04
使用ResLoader
ResLoader 的使用非常简单,下面是一个简单的例子。
我们可以点击 dump 按钮来查看当前的资源总数,点击 cc.load、cc.release 之后分别 dump 一次。
可以发现,开始有 36 个资源,加载之后有 40 个资源,而执行释放之后,还有 39 个资源,只释放了一个资源。如果使用 ResLoader 进行测试,发现释放之后只有 34 个资源。
这是因为前面加载场景的资源也被该测试资源依赖,所以这些资源也被释放掉了。只要我们都使用 ResLoader 来加载和卸载资源,就不会出现资源泄露的问题。
示例代码:
可以看到上面的例子是先移除节点,再进行释放,这是正确的使用方式。如果我没有移除直接释放呢?
因为释放了纹理,所以 Cocos Creator 在接下来的渲染中会不断报错。
ResLoader 只是一个基础。直接使用 ResLoader 我们不需要关心资源的依赖问题,但资源的使用问题我们还需要关心。
在实际的使用中,我们可能希望资源的生命周期是以下几种情况:
跟随某对象的生命周期,对象销毁时资源释放
跟随某界面的生命周期,界面关闭时资源释放
跟随某场景的生命周期,场景切换时资源释放
我们可以实现一个组件挂在到对象身上,当我们在该对象或该对象的其它组件中编写逻辑,加载资源时,使用这个资源管理组件进行加载,由该组件来维护资源的释放。
界面和场景也类似。项目代码位于:https://github.com/wyb10a10/cocos_creator_framework ,打开 Scene 目录的 ResExample 场景即可查看。
以上就是本次的分享,
如有问题或新的想法欢迎留言嗷~
如果您在使用 Cocos Creator 2D/3D 的过程中
get 了独到的开发心得、见解或是方法
欢迎分享出来
帮助更多开发者们解决技术问题
让游戏开发更简单~
期待您与我们联系~
领取专属 10元无门槛券
私享最新 技术干货