我打算再做一个管理器来控制释放,就是界面关闭的时候,把要清理的资源,添加到管理器的释放队列,然后做个定时来释放资源
/** 等待释放的资源uuid */
private _waitDelete: Map<string, number> = new Map()
onLoad() {
//循环进行资源检测
if (CC_PREVIEW) {
this.schedule(() => {
cc.log(assets)
}, 5)
}
if (this.autoRelease) {
//引擎内置资源常驻
assets.forEach((asset, uuid) => { asset.addRef() })
this.schedule(() => {
this._doRelease()
}, this.releaseDelay / 2.0)
}
}
private _doRelease() {
if (this._waitDelete.size) {
let now = performance.now()
this._waitDelete.forEach((deleteTick, uuid) => {
//超过时间进行删除检测
if (now >= deleteTick) {
let asset = assets.get(uuid)
if (asset) {
//@ts-expect-error
cc.assetManager._releaseManager._free(asset)
}
this._waitDelete.delete(uuid)
}
})
}
}
/**
* 尝试删除(将其放入待删除容器中,真正删除在定时器中调用)
* @param uuid 资源的uuid
*/
public tryRelease(uuid: string) {
let deleteTimeStamp = performance.now() + this.releaseDelay * 1000
this._waitDelete.set(uuid, deleteTimeStamp)
}
恩,类似这样的,我记得cocos2dx,有这样的管理器
在js中,没有同时这事情,凡事有先后。
你的情况,
- 可能是先打开B界面时,进入了异步加载,判断资源加载过跳过。没进行资源引用,然后关闭A界面。A界面关闭时将本就加载完的资源释放了。
cocos的资源引用,是在资源加载完成时,才进行引用。这样没什么问题。但在这个异步加载的过程中,资源系统对业务(开发者)有什么骚操作是无法感知的,业务也无法对资源系统正在加载的资源进行干预(锁定,加引用)。
可以在上层做粗粒度的资源管理。
加载前就进行了自定义的资源引用。释放时要判断这个自定义的引用是否为0,为0才释放。
如果这样做,用你的情况就会是这样
先打开B界面,引用资源A,资源A引用=2,进入异步加载,判断资源加载过跳过。关闭A界面,资源A引用–,资源A引用=1,不释放。
大概这样。
同时只是表达两个步骤是接连在一起的,也就是同一帧的意思,肯定是会有先后的,这个就不纠结了
这里我是使用了addRef和decRef来做资源管理,至于在什么时候释放,是完全交给引擎处理。
之前在a,b两个界面同时都会动态加载统一个资源时,会出现这种关闭a后打开b的时候,b界面的资源加载出来是已经被释放了的情况。
我刚才想简单做个demo,但是测试的时候,又没问题了,估计还是使用的业务逻辑有问题,这个我后面再好好排查具体那块出问题
请问下,这里的decRef为啥要传false?
// cocos2d/core/asset-manager/utilities.js
clear (task, clearRef) {
for (var i = 0, l = task.input.length; i < l; i++) {
var item = task.input[i];
if (clearRef) {
!item.isNative && item.content && item.content.decRef && item.content.decRef(false);
}
item.recycle();
}
task.input = null;
},
你在释放资源A的时,不要在当前帧立马又加载资源A。你得界面应该是关闭打开切换太快的就造成你说的问题
加载新界面资源A资源A是异步的,释放上一个界面资源A又在下一帧。当下一帧释放资源A时,资源加载完成就出现问题咯
嗯,目前就是避免在同一帧,规范下内部开发的一些规范,先规避这样的问题
游戏主界面里面有许多副功能(个人信息,任务…),目前做法是打开副功能加载prefab,关闭释放相关资源,现在遇到个别玩家骚操作:频繁打开关闭副功能,然后游戏卡崩溃了。 定位到问题是虽然释放了资源,但这个只是从缓存中删除,内存并没有立即释放,js垃圾回收是定期自动清理内存, 这个问题有好的解决方法吗
cocos虽然没有马上释放,但是有释放标记的,要么引用计数增加不释放,要么有释放标记不让用的