解决iOS下cocos游戏重复启动的问题

【声明】原创文章,转载请联系我!

问题来源:

http://www.cocoachina.com/bbs/read.php?tid=1713866#1901755


解决方案如下:


按照官方给的demo的代码,再次启动相当于从APP启动的位置上重新运行一次代码,但遇到了崩溃的问题,定位在在ScriptingCore.hpp的ScriptingCore::runScript方法里面的
evaluatedOK = JS_ExecuteScript(cx, global, *script, &rval); 

这一行。



这个错误提示是指访问内存地址错误。经过对源码的分析,这是由于cocos2d根本就没有考虑多游戏场景导致的结果,所以为解决这个问题,需要对js-binding的源码进行修改或者添加额外的代码使之支持这种机制。经过多次试错,总结出的代码层次的主要原因是以下几个:
1、退出游戏时,默认的逻辑中,没有完全释放游戏资源,包括脚本资源和js-binding的资源;尤其是js-binding的资源,并不会因为窗体的关闭而释放;
2、js-binding的控制器,写成了一个单例,部分初始化的工作只在单例初始化的时候只做一次,所以即便在窗体关闭时释放了binding的资源,但第二次重启游戏的时候,由于单例已经存在,所以事实上一些相关的资源其实没有完全地重启;
3、在退出游戏释放资源的地方,由于默认单游戏的逻辑,cocos的源码中是有exit(0)这种C++层次的关闭程序的方法调用,从而导致了其他的崩溃问题。


可用的具体解决方案如下:
1、在游戏脚本调用关闭窗体的反射方法前,关闭游戏,释放游戏资源,即调用cc.director.end();




2、注释掉ScriptingCore.cpp文件里面398行的exit(0);一行。

这里,cocos只针对了iOS平台做了预编译,所以在安卓平台上,应该不需要考虑此步骤




3、注释掉ScriptingCore.cpp文件里面490行的initRegister()一行。
这里是ScriptingCore的构造函数,initRegister()是初始化注册器用的,只在ScriptingCore单例建立的时候调用。而initRegister()接下来我们需要手动调用,为避免重复,需要把它注释掉。



4、在ScriptingCore.h文件中,553行处,把initRegister方法的声明从private改为public,这样才能够被外部调用



5、在ScriptingCore类中添加一个叫做jsshutdown的方法

JS_ShutDown是SpiderMonkey里的API。官方对它的释义如下:

When yourapplication is done with SpiderMonkey altogether, use JS_ShutDown to free any remaining cached resources. (This is a merenicety if the process is about to exit anyway. But as that is not always thecase, calling JS_Shutdown isa good habit to get into.)





6、CCApplicationProtocol.h头文件中,添加以下两个方法的声明。

因为ScriptingCore并不需要暴露给APP的原生部分,对于原生所能调用的是cocos的Application对象,所以在这里封装这两个函数比较合理。




对应的,在CocosAppDelegate.h里面添加相应方法的声明。




这两个方法的实现:




从代码上可以看到,initRegister目的就是提供手动注册的方法,cleanMethod就是提供清理资源的方法。cleanup是默认提供的方法,之前在尝试过程中这么调用一直不成功,还是因为spidermonkey里面的资源还没释放,所以还需要调用下JS_ShutDown。


7、最后,在启动游戏的时候,先手动注册一下:




关闭窗体后清理资源。注意要在completion回调之后调用。




至此,js-binding的源码修改完毕,解决了上述问题


【再次声明】原创文章,转载请联系我!

发布了4 篇原创文章 · 获赞 2 · 访问量 2639

猜你喜欢

转载自blog.csdn.net/chengzhf/article/details/70275457
今日推荐