有场景A跟场景B,
场景A是当前场景,场景B是将要替换的新场景。

那么A场景的资源释放最佳时机是在什么时候呢?

这是释放资源的代码(注意要按这个顺序释放):

1
2
3
4
CCAnimationCache::purgeSharedAnimationCache();
SpriteFrameCache::getInstance()->removeUnusedSpriteFrame();
CCTextureCache::getInstance()->removeUnusedTextures();
CCTextureCache::getInstance()->getCachedTextureInfo();

1.
最开始我想到的,应该是在场景A的onExit里释放,试验了下,资源并没有被释放,说明当前纹理仍然在
被引用,即场景A的子节点并未remove。
后来查了下,发现每个场景的资源释放都是在一个叫dealloc的方法里,而这个方法是在onExit之后执行的。
也就是说在onExit里释放资源是不合适的做法。

2.
我突然想起来,每个类不都有个析构函数么?析构函数是在该类的对象被delete时调用的,
只要在A场景的析构函数里释放不就可以了?试验了下,发现也没效果,
仔细想想,我创建场景用的方法是Cocos2DX推荐的默认方法,即场景类继承一个Layer,
然后再createScene里创建一个Scene,再把当前类添加到Scene里。替换场景后,
该Layer被释放时,场景中的其他资源并不一定被释放,所以此方法也是行不通的。

3.
竟然场景真正remove子节点是在dealloc方法里,那么在dealloc里释放资源不就好?
可惜的是我根本就找不到有这个方法。于是放弃了。
后来百度了下场景的调用顺序规则:

1
2
3
4
5
6
7
replaceScene : SceneB
init : SceneB
onExitTransitionDidStart : SceneA
onExit : SceneA
dealloc : SceneA
onEnter : SceneB
onEnterTransitionDidFinish : SceneB

由此可看出,B场景的onEnter函数在A场景的dealloc之后执行。
而且
那么只要在B场景的onEnter里释放A场景的资源就可以。
试验了下,资源的确被释放了。

而且,释放资源是在B场景的init之后执行,这样的好处就是,假设场景B中用到场景A中的某些资源,
这些资源就不会被释放再加载,造成不必要的内存高峰。

4.
问题到此结束了吗?我也以为结束了,然后又发现新问题。
一旦我给场景过渡加上效果,以上方法就不灵验了,释放失败。

1
Director::getInstance()->replaceScene(CCTransitionFade::create(0.5f, SceneB::createScene()));

然后调试跟踪下执行顺序,发现问题所在了。
当有过渡效果存在的时候,执行顺序变成这样:

1
2
3
4
5
6
replaceScene : SceneB
init : SceneB
onExitTransitionDidStart : SceneA
onEnter : SceneB
onExit : SceneA
onEnterTransitionDidFinish : SceneB

没错,场景A并不会立刻结束,而是等到动画效果完毕后才结束。
但是我发现不管有没有使用过渡动画,最后执行的总是onEnterTransitionDidFinish,
那么我们只要将资源释放放在这里就行了。
经过试验,发现又失败了。。。
为啥,因为虽然dealloc方法是在onExit之后执行,但并不是紧追其后,也就是说,
有可能在onEnterTransitionDidFinish 之前,也有可能在其后,因此我们直接在
onEnterTransitionDidFinish 里释放资源并不一定可行。那该怎么解决?
这里我使用了延时释放的方法,在onEnterTransitionDidFinish 执行后过一段时间,
再调用释放资源的方法,这样就可以确保资源被释放。

1
scheduleOnce(CC_SCHEDULE_SELECTOR(SceneB::release), 2.0f);

5.
以上方法的确是可以将资源释放掉,但是不是我们所要的”最佳时机”呢?
仔细观察,B场景的init是在A场景的释放之前的,也就是说,在B场景诞生,A场景彻底释放
的短时间内,会存在A,B场景的所有资源共存的现在。这个时候内存达到巅峰。如果A场景
跟B场景的资源所占内存都非常大的时候,或许会造成崩溃。
那么我们应该如何解决?

目前我的解决方法就是在场景过渡的时候增加一个过渡场景,也就是Loading场景,Loading场景
本身所需的资源并不多,在A场景资源释放完毕后,再开启B场景的资源加载。

COCOS2D 释放资源的最佳时机的更多相关文章

  1. cocos2d源码剖析

    1. TextureAtlas http://www.cocoachina.com/bbs/read.php?tid-311439-keyword-TextureAtlas.html 2. Label ...

  2. cocos2D(三)---- 第一cocos2d的程序代码分析

    在第一讲中已经新建了第一个cocos2d程序,执行效果例如以下: 在这讲中我们来分析下里面的代码,了解cocos2d的工作原理,看看屏幕上的这个"Hello World"是怎样显示 ...

  3. 三、第一个cocos2d程序的代码分析

    http://blog.csdn.net/q199109106q/article/details/8591706 在第一讲中已经新建了第一个cocos2d程序,运行效果如下: 在这讲中我们来分析下里面 ...

  4. 小尝试一下 cocos2d

    好奇 cocos2d 到底是怎样一个框架,正好有个项目需要一个游戏框架,所以稍微了解了一下.小结一下了解到的情况. 基本概念 首先呢,因为 cocos2d 是基于 pyglet 做的,你完全可以直接用 ...

  5. 采用cocos2d-x lua 制作数字滚动效果样例

    require "Cocos2d"require "Cocos2dConstants"local testscene = class("testsce ...

  6. Cocos2d 利用继承Draw方法制作可显示三维数据(宠物三维等)的三角形显示面板

    很久没有写博客了,这段时间比较忙,又是搬家又是做自己的项目,还有太多琐碎的事情缠身,好不容易抽出时间把最近自己做的一些简单例子记录一下. 在我的项目中,我需要一个显示面板来显示游戏中的一个三维数据,例 ...

  7. iPhone开发与cocos2d 经验谈

    转CSDN jilongliang : 首先,对于一个完全没有mac开发经验,甚至从没摸过苹果系统的开发人员来说,首先就是要熟悉apple的那一套开发框架(含开发环境IDE.开发框架uikit,还有开 ...

  8. using 释放资源

    我们知道使用C#程序访问数据库资源需要几个步骤:创建连接,打开连接,访问数据库,关闭连接,基本架构如下: SqlConnection conn = new SqlConnection(connStri ...

  9. cocos2d学习记录

    视频 - http://www.manew.com/forum-105-3.html一个论坛帖 - http://www.zhihu.com/question/21114802官网 - http:// ...

随机推荐

  1. NuGet在创建pack时提示”The replacement token 'author' has no value“问题解决

    在创建pack时出现了“The replacement token 'author' has no value”的错误提示. 解决方法: 1.可能程序没生成过,在解决方案上重新生成解决方案,注意Deb ...

  2. PostgreSQL Reading Ad Writing Files、Execution System Instructions Vul

    catalog . postgresql简介 . 文件读取/写入 . 命令执行 . 影响范围 . 恶意代码分析 . 缓解方案 1. postgresql简介 PostgreSQL 是一个自由的对象-关 ...

  3. Linux File System

    目录 . Linux文件系统简介 . 通用文件模型 . VFS相关数据结构 . 处理VFS对象 . 标准函数 1. Linux文件系统简介 Linux系统由数以万计的文件组成,其数据存储在硬盘或者其他 ...

  4. ubuntu常见错误--could not get lock /var/lib/dpkg/lock -open

    最近研究ubuntu,用apt-get命令安装一些软件包时,总报错:E:could not get lock /var/lib/dpkg/lock -open等 出现这个问题的原因可能是有另外一个程序 ...

  5. git本地分支

    1. 新建并切换到该分支 $ git checkout -b iss53 Switched to a new branch 'iss53' 相当于: $ git branch iss53$ git c ...

  6. 帝国cms一些常用的修改路径

    1.信息提示改成弹出框提示 修改e/message/index.php 2.修改提示信息 语言包e/data/language/gb/pub/q_message.php 3.文章设置权限后没登录提示模 ...

  7. global--命名空间的使用(一些零散的js方法)

    var GLOBAL = {}; GLOBAL.namespace = function (str) { var arr = str.split('.'), o = GLOBAL; for (var ...

  8. 初识JSLint及建议JS编码风格

    可能都或多或少的知道JSLint是一个JavaScript的代码质量工具,一个JavaScript语法检查器和校验器,它能分析JavaScript问题并报告它包含的缺点. 被发现的问题往往是语法错误, ...

  9. Win7、Ubuntu双系统正确卸载Ubuntu系统

    正确的删除ubuntu方法如下: 第1步,修复MBR 1.进入win7,下载个软件MbrFix,放在C:windowssystem32文件夹中 2.点击开始>所有程序>附件>命令提示 ...

  10. socket传数据并记录到文件中

    最近在新项目中要通过socket传一些数据,下面是程序: 功能: 将客户端发送的json数据写入到日志文件中,如果数据不是json的,丢弃. 程序如下: #!/usr/bin/env python # ...