去年,古风模拟经营类手游《江南百景图》成功破圈,成为年度现象级爆款。如何将它搬到小游戏平台?是转换还是重写?使用哪些技术方案,能在包体大小仅为原版1/20的同时,达到与 App 版相当的游戏体验?椰岛小游戏研发负责人大城小胖,带着他近300页的 PPT,在 Cocos 的两次线下活动中做了全面的技术分享。
转换 or 重写
《江南百景图》App 版游戏包大小有 600+M,上线前期还有部分用户反映游戏运行时手机发热严重。而小游戏版在经过立项选型后,决定使用 Cocos Creator 重写,仅用了1天就做出了 Demo。经过4个月的优化,我们最后将包体压缩到 30M 左右,同时保证游戏体验与 App 版相当。
优化的过程中,我们也做了以下工作,其中 代码 部分需要重新设计和编写。
渲染优化
原生版本的《江南百景图》移植到小游戏首先需要解决的就是 耗电高、易发烫、Draw Call 高等问题。
合批
合批是降低 Draw Call 最快也是最有效的方式。优化同样的 Texture,将多张的图片合并到一张图集上,这样不论要生成多少张不同的图片,都不会打断合批渲染,Draw Call 也就降低下来了。
但是《江南百景图》的资源非常多,每个玩家使用资源的顺序也不尽相同,如果玩家使用的资源分别在不同的图集上,还是会导致合批渲染被打断,产生 Draw Call。因此,针对这一情况,我们采用了 Multi-Texture 的方式进行了优化,其原理是将传统的判断是否在同一张图集,转换为判断是否在 同一批图集,这样就大大减少了 Draw Call 产生。
另外,通过 gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) 这个指令,可以知道在一台设备中 Shader 最多支持几张图集。测试发现目前 90% 以上的手机至少支持8张,因此我们将批图集的数量设置为8张。因为一个批次有 8 张图集,所以我们是通过这个 idx 判断某张图用的哪个图集,代码也很简单。
动态合图
小游戏版本采用了 Cocos 的动态合图机制,这样在 CDN 下载的图片也能进行合图。而为了提高合图的效率,避免浪费空间,我们会将长度或者宽度特别大的图片进行裁剪。
例如左图中的旗杆,由于图片太长,在动态合图时会导致空间浪费,因此我们将这张旗杆的图片裁剪成两张,如右图所示,再在项目中进行拼接处理。
采用同一个材质资源
在《江南百景图》中,玩家移动地图时,原本在显示范围外的图片将从水墨色变为彩色。
传统的方案是改变图片材质,当地图移动到要显示的节点时,节点一个一个地进行材质的切换,达到一个 “淡入淡出” 的效果。但是在项目中尝试之后,我们发现这样会导致 Draw Call 上升,而且拖拽地图又是一个很频繁的操作,游戏中实际效果较差。
因此在这里我们将所有城市物体资源,无论是人物还是建筑、常态还是淡入状态,都用统一的 Material、并使用顶点数据传递“时间参数”,以此节约性能消耗,最终达到所有建筑和人物的创建、移动、销毁等全都只需要一个材质就能够完成。