问官方个问题,场景切换和资源释放的正确方式 应该是个什么规则?

这里有两个思路,1.你可以在编辑器中对应场景选择自动释放资源

这样在加载新场景时不需要你手动去释放资源。

2.如果你想要手动控制的话
cc.loader.releaseAll();
cc.director.loadScene(“NewScene”);
这样用是有问题的,loadScene是会去异步下载新场景,中间肯定会有报错的。所以要等到场景下载完之后开始加载新场景时再释放上个场景资源

loadscene接口有两个回调,你可以在里面写释放上个场景的资源,但是注意,这个时候就不能用releaseAll了,因为,现在所有资源里面包含了新场景的资源和老场景的资源。所以只能用release方法释放老场景的依赖资源。
场景的依赖资源可以通过场景的属性dependAssets获得。

另外,注意一下,在loadscene这个函数的执行过程中,cc.director里面记录的当前场景会变成新场景,所以不能在
回调函数里面通过cc.director.getScene().dependAssets这种方式获得老场景的依赖资源,因为cc.director.getScene()已经是新场景了。必须在加载场景之前,先把老场景依赖资源缓存一下。应该可以这么写

var oldAsset = cc.director.getScene().dependAssets;
cc.director.loadScene('newscene',null,function(){
      cc.loader.release(oldAsset);
})

注意,第二种思路是建立在新场景和老场景之间资源不共用的情况。如果有资源共用,这种释放也会把新场景用到的资源释放了,所以如果是这种情况的话,你可能需要将老场景的依赖资源和新场景的依赖资源进行比对,把不共用的资源释放掉,第一种思路中里提到的设置autorelease其实就是cocos帮忙做这件事。所以如果场景中有共用资源的话,还是设置autorelease为true吧,方便一些

5赞

test.rar (688.8 KB)

版本 ;202

例子很简单 没有任何图片资源都
模拟器里报错:
Simulator: E/jswrapper (271): ERROR: Uncaught TypeError: Cannot read property ‘0’ of null, location: src/cocos2d-jsb.js:0:0

小游戏里报错:
WAGame.js:4 gameThirdScriptError
Cannot read property ‘0’ of null
TypeError: Cannot read property ‘0’ of null
at Object.fillBuffers (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:604776)
at v._commitComp (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:614485)
at g.132.y._render (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:560990)
at g.132.y._children (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:561510)
at g.132.y._children (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:561510)
at Function.132.g.render (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:562683)
at visit (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:614717)
at Object.render (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:416778)
at 26.cc.Director.mainLoop (http://127.0.0.1:40503/game/cocos2d-js-min.20e44.js:1:123116)
at callback (http://127.0.0.1:40503/game/libs/engine/Game.js:26:22)

你好 在资源释放时,我们不推荐在游戏运行时调用releaseAll() 释放掉 load _cahce 中的所有缓存资源(这不单单是你这个场景的资源而是整个游戏环境的),除非你一定需要这么做,因此这将会造成游戏场景运行异常导致后续不可预期的错误。
如果你希望释放掉场景中的某一部分资源可以将该资源提供给release,再通过cc.loader.release();来释放。
https://docs.cocos.com/creator/api/zh/classes/loader.html#release
我们会给导致报错的出错部分加上逻辑保护,让它不会再那么轻易的暴露在用户面前。

我的场景资源的规则是这样 ,每个场景之间 没有共享资源, 那么每进入一个新的场景 会有这场景本身带的资源 和 loadRes动态加载的资源 包括声音 图片 动画 还有PREFAB 等各种东西,那么是不是可以这样
把场景选择成自动释放资源模式 然后 在新的场景onLoad里最开始处,先手动releaseRes 前一个场景的所有的对应的loadRes,是不是就可以保证 前一个场景的所有的资源 都被释放干净了?

自动释放资源会将你当前场景中所引用到的资源释放掉,没有必要再去释放一个已经被释放的资源对象。

引用到的资源释 是不包括loadRes动态加载的资源把,这个还是得手动releaseRes 的把?

是的

2赞

释放脚本动态加载的资源还是很麻烦。试想有一列表,每个列表项滚动到可视时会加载一张远程图片。那么难道还要记录下加载了哪些url,然后再通过cc.loader.release去释放?
我觉得应该有个更好用的api。有没有方法能释放所有通过cc.loader动态加载的资源?

这个很麻烦,还要记录前一个场景动态加载了哪些资源

直接打勾自动释放资源- -

这个只会释放场景中引用到的静态资源,脚本动态加载的没法释放

https://forum.cocos.com/t/2-0-2/68173?u=bophie

游戏开发过程中,控制资源释放会有很多复杂的情况,但无论多复杂通过引用计数是可以去精准控制的,但前提是引用计数需要正确统计,那么就需要官方提供获取资源依赖关系的API,而且需要高效无副作用。

切换场景一次性释放所有资源,这种都不能在大项目中符合要求,因为这很浪费性能(前一个场景中使用到的部分资源,在下一个场景也大部分会重新使用到,释放了这部分资源是很不应该的)。

需求需要精准控制那些不再使用的资源,而且还不能仅限于切换场景,随时随地都应该可以去正确释放那些不正在被使用的资源。

cocos2dx年代有个releaseUnusedRes,好像是这个名字吧

我就想问下这种情况怎么处理,难道真要记录一下加载了哪些资源?

可以通过API cc.loader.getDependsRecursively() 获取一个预制物所需要的所有依赖资源

释放资源可以使用API cc.loader.release(uuid)

你需要的那种调用一个api然后卸载掉当前所有没有被使用的资源的功能,目前是没有的,这种功能就是要引擎提供一套内存管理解决方案

我觉得 最保险的就是这样了 你加载了哪些东西 你自己肯定知道,引擎不提供更好的方式的时候 就只能靠你自己了

官方这边确实应该理一个方法 最近也都是遇到这种问题 切换场景各种销毁停止
this.node.stopAllActions();
this.unscheduleAllCallbacks(); // 销毁所有定时器
依然报错 太累了

挖坟,就是目前也没有统一接口可以处理掉旧场景的资源和代码执行?

mark

我们需求很简单,你只提供明确的释放接口就好,不用担心我们释放后,其他地方有引用的问题,这个我们自己控制就好,现在是做稍微大一点的项目,内存就控制不住的往上涨,也不用提供demo你们自己试吧