关于对象池中的prefab应该如何释放?

目前有几个问题,
注,原生 环境下
1,


这里放回对象池中的prefab会变成node,
然后使用
let deps = cc.loader.getDependsRecursively(obj);
cc.loader.release(deps);
会报
Warning 4800, please go to https://github.com/cocos-creator/engine/blob/master/EngineErrorMap.md#4800 to see details. Arguments: [object Object]

想知道正确释放对象池中的prefab
目前我是这样释放的,不知道对不对
this._objectNodePool[key].clear();//key为prefab的path
let deps = cc.loader.getDependsRecursively(key);
cc.loader.release(deps);
这样不知道能不能释放干净,因为不是每个对象都释放的
2,
因为使用对象池,不过在切换场景时,有的没有被收回到对象池里,那这些对象应该如何处理,是在切换时,把没有回收的prefab收回到对象池?还是不用处理?(感觉应该收回,统一处理,但这样好像有些很麻烦呢。。。要时时记录对象,然后释放时就会产生上面的问题)

:joy:~~~

http://forum.cocos.com/t/prefab-prefab-destory/46253/5?u=111923

现在内存是有释放,但是还是有很多残留,不知道是不是对象池的原因,或者没用好对象池?

这个应该是 bug,不知道你是什么平台,什么版本?

deps 打印一下是什么?

只要对象在场景里,就不应该放在对象池

原生,ios, 1.5.1b3版本

这个意思是,在场景里的(从对象池中取出来的) 就不用管理了,切换场景时会自动释放?

打印的是这些,应该是prefab引用的文件
res/import/9c/9c96a52b-d252-47d5-b8f2-033dacef19ff.json,res/raw-assets/resources/res/ui/common.png,res/import/25/257a8616-b17f-4a2c-827b-873d3267dad1.json,res/import/3c/3c4725f2-e68a-434b-a5c8-6cac70740391.json,res/import/27/27d66eea-5ff5-4742-9694-b0a75a00bb84.json,res/raw-assets/resources/res/ui/language/chinese.png,res/import/ba/ba3c1ffe-5df6-4d82-9002-8f6def259ff7.json

不是,是你如果对象添加到了场景里,就不应该同时存放在对象池。

应该可以,打印出来的数据挺正常

4800 那个 warning 你可以在报错的位置下断点:

cc.warnID(4800, assetOrUrlOrUuid)

看看这里的 assetOrUrlOrUuid 的值是什么,看你的 log 应该是一个对象,可能只是这个对象不是 asset,不一定影响你释放资源

放到场景里的都是从对象池中取出的,get出来的,所以只在场景里有,我的意思是,从对象池中取出的放到场景里,还用在切换场景时,把取出来的再放到对象池里么?然后统一释放,还是切换场景时,会把这些对象池中取出的prefab跟着场景一起释放,不用代码再处理了?

不过这个只是释放了一次,我担心原来对象池中的对象还持有这些文件(比如没有收回到对象池中的对象等),导致内存释放不完的情况,因为现在发现释放会有残留,而且多次cc.sys.garbageCollect();也不减少,所以感觉应该是对象没有释放干净,但又不知道哪些没干净。。。

切换时会自动释放掉,不过这样就起不到对象池的作用了。想要缓存的话就设置成常驻节点或者切换场景时从场景移除放到对象池

这个只能你自己检查看看了

这是断点图,里面没有_uuid这个属性
我感觉就是prefab 放到内存池里时,转成Node的原因,我的放的方式是pool.put(prefabScript.node)

我这个对象池只在这个场景中使用,所以切换场景时要把对象都清空,还有把其他场景不使用的资源都释放掉,现在的现象是有一部分残留,不知道是不是没有把留在场景里的对象的引用释放掉,因为一释放就报4800这个错,
现在脑子有点乱。。。

这个 obj 只能是 prefab,不能是 instantiate 后的 node

那应该如何转成prefab呢,我的使用流程是这样的
let prefab = nodePool.get();//从对象池中取出
let script = prefab.getCoXXX(“XXX”);//获取脚本
script …使用
回收到对象池
nodePool.put(script.node);//这里如何把script转成prefab?//这里应该如何回收呢?

这里不应该回收啊,你都用对象池了,证明对象池里有很多相同的 node,这些 node 共用了同一个 prefab。那你一回收剩下的 node 引用到的资源不就失效了?

那对象池的使用方式不是 get 使用 put 这三个么?难道不用put回?
这里好像有点乱,我重新整理一下
我的使用方式是这样的
1,从对象池中取出prefab对象
let prefab = nodePool.get();//从对象池中取出一个prefab
2,获取脚本组件
let script = prefab.getCoXXX(“XXX”);
3,使用脚本组件
//这里省略一万行
4,脚本组件对应的怪死亡,回收到对象池,等待下一波重复使用
//这里回收应该如何写?
nodePool.put(script.node); //我是这么写的,乎不对?//因为放回去的不是prefab了,而是node了

难道不是这样使用对象池么?
也许应该在脚本里要保存一份prefab自身?

我觉得你好像混淆了 prefab instantiate 出来的节点和 prefab 资源本身。

instantiate 得到的 node 并不是资源,不需要从 loader 删除,你传入 loader 也无法正常获得原始 prefab 的依赖。你需要传入的是和 cc.instantiate(prefab) 中参数一样的 prefab 资源对象。

节点回收池仅针对节点
loader 资源管理仅针对资源本身,与节点无关

以上

好像明白了,,不过还是有几个问题需要确认一下哈,
1,let node = cc.instantiate(prefab) ;
这里的node与prefab的关系 与 jsonData = JSON.parse(jsonPath) 的关系一样?
node <-> jsonData
prefab <-> jsonPath
是这样么?
2,

这句话的意思是,对象只要释放自己就可以了,资源引用跟对象没有关系?(是不是只要对象distory了,就对资源的引用释放了?)
我在另一个帖子里看到的


这个是不是说下面的写法就可以了
nodepool.clear();
let deps = cc.loader.getDependsRecursively(key);
cc.loader.release(deps);
这样就能正常释放了?

不太准确,node 是 prefab 生成的没错

对象 destroy 后,就会释放对资源的引用。资源是否 通过 loader release 取决于用户是否还要用到资源。比如这里对象池中的其它 node 仍然会用到,那肯定就不能释放啊。

是的

好的,多谢多谢~~~

预制体资源(prefab)通过这方法释放之后,下次用的这个预制体实例化后,资源还会在吗

1赞