我们游戏项目中的 ui 实现方式,采用的是用 cocostudio 编辑ui,导出 exportJson 和大图的方式实现的.
这样实现一直都存在一个问题: 当一个页面用到较多的 ui模板时,加载速度会非常慢. 比如点击一个 按钮,展示一个 由 7,8 个ui模板组成的 页面时,要花费一两秒的时间,体验非常不好.
导致问题的根本原因是 WidgetFromJsonfile() 这个函数非常慢。
起初我怀疑是 io 的问题, 也就是说认为是这个函数里面调用 CCfileUtils::sharedfileUtils()->getfileData() 这个函数慢,但后来验证发现这个函数花费的时间非常少,
影响性能的是这个函数里面调用的 WidgetFromJsonDictionary(WidgetTree); 函数非常慢。这个函数是在根据 Json 字符串解析出各个 ui控件。
为了解决卡顿的问题,我尝试了以下几个方法:
1. 相同 ui模板交替位置,实现无限循环。
比如我们有个页面,需要展示 几十个 相同 ui模板组成的 List vIEw.这时可以计算 当前页面最多显示 n 个,在此基础上 +2,也就是一共调用 n+2 次 UIHelper::instance()->createWidgetFromJsonfile() 函数。
利用这个 n+2 个控件,当向下移动时,顶端控件挪下来,向上移动时下端控件挪上去,来实现几十个 ui模板的滚动。
这样的方法虽然节省了不少时间,但是即使仅读取 n+2 次 ui 模板,还是要花费1 ~ 2秒,效果不理想
2. ui 控件不从 Json file 解析,而从内存中拷贝
我们项目的 cocos2dx 版本比较老, UIWidget 没有 clone() 函数。
起初我就根据 UIWidget* CCSGUIReader::WidgetFromJsonDictionary(const rAPIdJson::Value& data) 函数里调用的各个子函数
setPropsForbuttonFromJsonDictionary() setPropsForCheckBoxFromJsonDictionary() 等等函数,来按照这些函数写一些 属性赋值函数。但是写得很辛苦,而且复制效果也不好,许多不同的 UIWidget 类需要 不同的参数设置,很难保证正确性。
后来下载了 cocos2dx 2.2.5 版本, UIWidget 以及它的各个子类都实现了 clone() 函数。我把这些 clone() 函数移植到了我们项目里面。
但结果非常悲剧 : 用 UIWidget 的 clone() 竟然 比 每次读取 Json file 的方法更慢! 并且在 2.2.5 版本上试验一番,也证明了 UIWidget 类的 clone() 函数效率低下。
所以从内存中拷贝这样的方法行不通。
3. 给游戏增加 loading 界面,在进入游戏前缓存足够的 UIWidget
为此写了一个 singleton 的类 UIPool ,在游戏开始时加载足够多的 所需要的 UIWidget 控件,修改 UIHelper::instance()->createWidgetFromJsonfile(),当 UIPool里面有相应的空闲控件时,直接拿来用,否则再去 调用 read from Jsonfile 相关函数。
起初以为这个UIPool 实现起来, 对缓存的 UIWidget 的内存控制会比较麻烦,但是写了代码后发现,采用 CCDictionary 里面存储 n个 CCArray ,每个 CCArray 存储控件实例的方式,实现起来非常简单。并且 CCDictionary 和 CCArray 都可以使用 cocos2dx 的内存管理机制,实现起来很方便。
这样,使用方法3 和 方法1 相结合, 就可以消灭大部分游戏中由于 UIWidget 读取导致的的严重卡顿了。
总结以上是内存溢出为你收集整理的解决 cocos2dx UIWidget 加载速度慢造成的游戏卡顿全部内容,希望文章能够帮你解决解决 cocos2dx UIWidget 加载速度慢造成的游戏卡顿所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)