iOS 微信小游戏物理性能问题研究

之前发过一个帖子:微信小游戏DrawCall和模拟器相差巨大
http://forum.cocos.com/t/drawcall/59139

后来一直也没找到原因,直到最近看了一些关于jit的文章,大概是问题所在。

jit优化和关闭的性能差4到5倍,ios的Safari是开启了jit,而微信小游戏没有jit。
结果就出现了浏览器运行游戏非常流畅,而微信小游戏却非常卡顿。

顺着这个思路想去优化游戏中js的计算逻辑较多的地方,结果都没有太大帮助。
然而当我去不断减少游戏中的画面元素,缩减地图大小,帧率就逐渐提高。

在模拟器上drawcall都很低,说明drawcall的合并是没有什么问题的,
那么我得出的结论是:

在jit无法开启的平台下,图片的合并渲染是性能低下的罪魁祸首!

如果是这样的话,对于类似tilemap地图的游戏,是不是很绝望?
因为超过一定大小就无法愉快玩耍,更不用说再加上其他游戏逻辑了。

以上是我得出的结论,特别希望官方纠正我的判断是否妥当。

还有对于类似这样的游戏地图式的场景,能否指条性能优化的明路。

先行谢过。

9赞

顶一下,没人关注看来大家性能都很不错

小游戏据说是用opengl渲染的。

另外,我的2款微信小游戏都上线大半个月了,性能问题没有担心过,很流畅。一个游戏是含有大量动画,一个游戏使用了isometric map。

游戏名是啥?我来用我的手机测测

游戏名是啥?我也来看看

看了一下你那个帖子后面的回复,看起来确实挺奇怪的,首先确认几点

  1. iOS 小游戏无法开启 Jit 会导致 JS 运算性能降低
  2. Jit 开启与否和 Draw Call 数量没有关联
  3. 我推测微信小游戏平台统计的 Draw call 其实是 OpenGL call 的数量,这个我会跟微信确认

我仍然认为 iOS 小游戏和模拟器的 Draw call 应该没有差别,因为 draw call 合并是纯 JS 逻辑,只要资源和逻辑没有变化,那么 Draw call 不受平台影响。这点你可以使用 2.0 来确认,2.0 开启调试模式,小游戏上也可以看到引擎统计的 draw call 数量,看看和 Web 端是否一致。

如果 draw call 真的差别很大,那么可能就是性能低下的罪魁祸首,跟 jit 关系并不大了。如果实际 draw call 接近,那么问题原因应该仍然是 JS 逻辑的性能低,这点可以通过使用开启 debug 的 iOS UIWebView App 来连接 Safari 远程调试确认(不要用 Safari,Safari 有 JIT)

1赞

再问一下游戏的名字,是不是已经上线?微信那边可以通过你的线上版本来调试

大佬,小游戏中经常出现闪退,是什么原因呢?大多情况都ios 6 闪退。我看了性能参数.基本稳定在cpu占用29%,内存380m,业务内存260m。现在不知道从哪些地方入手,解决这些问题。

你是说 iPhone 6 把,内存问题,iPhone 6 内存只有 1G

首先得感谢你的详细回复!

先说下draw call的和微信小游戏显示不一致的问题,这点在我后来的测试中找到了问题所在。在地图上有些物体(如可被击碎的物体、提前预制的子弹)在游戏过程中会产生粒子效果,所以初始化地图和场景中的物体时,挂在粒子的物体产生了多余的draw call。在2.0之前的版本粒子的图片精灵是texture不是spriteFrame,所以我确定这部分的粒子都增加了draw call的次数。不过在cocos 模拟器中并没有增加这部分draw call显示,我猜测是不是统计的时候没算上,可能是bug吧。

后来我把挂在到物体的粒子做成需要触发才动态加入和销毁,这样初始化场景后draw call基本和模拟器一致了,在游戏过程中draw call还是会和模拟器有些不一致,但也只是小于10左右的差别,我也就没在意了。

上面的解释也是表明我也认为draw call并不是导致性能低下的原因(对于我的游戏来说),那么也就写了这篇帖子来求助。如你所说,不是draw call原因的话,那还是因为js逻辑的性能低。我还没有用你说的方法去debug,但我也能猜到这个情况了。

所以我也主要是想请教在这样的情况下,我能如何优化?

tilemap地图型,每一个tile像素8080。格子数量小的地图2020,总地图像素约16001600,地图大的格子数量达到5050。
基本上我测试一个主角在这样的地图上移动就掉帧的厉害。

如果说要去优化游戏逻辑,没啥优化空间了,在chrome调试也就耗时物理系统和碰撞系统耗时一点了,也能接受。但对于js的性能低导致底层渲染逻辑执行慢,我就感觉有点无助了。

去减小地图大小,降低图片质量?或是怎样往哪个方向去平衡呢?

ps:游戏还没有上线,不过快要上线了,可惜地图稍大就只有十几帧,真没法上线啊。

啰嗦了一堆,真是抱歉,还是感谢!

准备弄一个demo的时候有重要发现,我发现把地图上有挂载物理碰撞的节点,那么纯图片渲染的地图并不掉帧,但是当我恢复物理组件,地图上有几十个有物理组件的节点帧数就极具下降。

换句话说是js在物理运算耗时导致性能差?总算是颠覆我之前的理解,我一直猜测图片的底层渲染性能差。

那么具有过多的物理组件场景,能如何优化呢?

因为1.9版本物理碰撞检测经常报错,所以碰撞检测都是用onCollisionEnter来判断,于是每一个碰撞体都挂了Box collider组件,一个地图上大概有几十个碰撞体。

今天我把box collider组件都删掉,碰撞检测换做用物理系统的onBeginContact来判断(2.0版本的物理碰撞没异常了)。结果小游戏的性能大概提升了1倍左右。

我不太清楚为什么会这样,物理系统用的c++实现反而性能好于普通的碰撞系统检测?

总之这样改了之后有很大提升,这个现象反馈给你们也看看吧,对于微信小游戏的性能优化应该有价值。

再感叹下没有启用jit的小游戏性能调优真是如履薄冰。

1赞

我测试过500多个dc和100多个是差不多的.js在计算碰撞这块效率极低…慎用…做好区域碰撞.

你可以试试100x100的简单矩形碰撞.如果在每帧都去计算,帧率会很低- -.碰撞可以不用每帧去计算,比如每两帧计算,可以减少一半的计算量.还有就是按区域检测碰撞.实际上不需要遍历地图上所有的碰撞体.可以计算下最大的包围盒是多少,远离玩家的包围盒就关掉就好了.只开启附近的物体包围盒检测.

我的地图编辑器快公布了,不防等几天。

https://www.bilibili.com/video/av21058852

这是几个月前我发的群内测试版视频,因为是针对数据对像的,无在乎地图大小,所以你说的问题也不存在。

软件并不简单,所以你最好先看看视频。那之后的时间我做了一个平面RPG,一个横版进行测试。其中横版是由一个完全没做过游戏的人,设计的关卡。一切都还算顺利。

现在我在对对像,动画碰撞控制,数据统计等进行加强,比视频上的功能更上一层,发布也就在这几天了。

哥们你建议的真到位,物理系统的步长用的默认的1/60,真是计算频率太高了,影响了性能。
我一怒之下把step改成了6,性能又提升了近30%。

还有你说的包围盒思路,我在后期优化时做了屏幕外的物体不执行逻辑,差不多的意思。

物理步长调整后,物理计算的性能损耗解决了,但还有优化空间。因为我关闭物理系统后,大地图比小地图的帧率还是低10到15帧,这说明渲染上的性能损耗还是存在。

总结一下我这个游戏的性能瓶颈,其实是两大块:
底层渲染逻辑耗时,碰撞组件及物理计算耗时。

碰撞及物理计算我优化的差不多了,剩下渲染的耗时(draw call已经很低了)还待优化。还希望有高手提供优化思路。

感谢你的建议。

我看了视频,很赞。里面有很多实用的高级特性。如果有以下能力就更好了:

1、mac版编辑器:sweat_smile:
2、发布后有完整的实例demo
3、微信小游戏上的性能运行指标(没办法,被性能折腾过的痛),最好包括块大小,地图大小,碰撞体数量等维度

顶黑科技!

渲染这块其实可优化的点很少的.dc减少到一定程度就很难去优化了.减少单帧提交顶点数量,缩小贴图尺寸,pvr,etc,像素格式,缓解显卡带宽的压力,这些其实是牺牲画面质量来保证速度的.
如果地图是静态的,可以用static的方式,只绘制一次到rendertarget,合并到一个sprite里,然后就可以把其他的节点删除掉了,这样可以减少大部分的node.update.整个地图绘制一次之后只有一个sprite,要注意2048x2048的贴图限制.可以合并成几个sprite.
地图上能合并的都合并掉.

大地图和小地图帧率不同大概率还是js的效率问题.
cocos底层做过裁剪,地图大小不影响单帧的渲染对象数量.但是大地图意味着node多,节点树transform计算是少不了的.可以把引擎代码的updatetransform的计算注释掉看看.最主要的还是要地图只保留地图的数据,显示时动态去载入地图.不管地图多大,同一时刻只存在屏幕大小的地图格子.

js和unity内核的mono的性能自然不能比。需要的优化也很多。

优化这个工作,其实是慢工出细活,要慢慢磨的。

我们的项目,以前已经觉得写的很优化了,但是巨卡无比,内存占用550mb左右,安装包空间也有点不够。

现在几个月过去了,项目功能加了一倍左右,但是反而不卡了,内存只占用100mb,安装包空间还省出了不少,多放了不少本地资源。

靠的都是一点点的优化。每个卡都是有原因的。这里面坑很多,不可能在这个帖子都说出来,总之就是要耐心的磨。。

举几个例子:
如果cocos的轮子不好用就尽量用自己开发的轮子,
游戏中相对闲置时默默加载资源,
做好贴图的Clipping,
看看有哪些开销大的function在同一时刻被重复调用了