能够在乱世中_畅销 SLG乱世王者深度优化方案

《乱世王者》是由腾讯天美工作室出品的一款战争策略手游,2017 年 8 月开启测试,数天之内便取得了 App Store 中国区畅销榜前三的成绩,充分体现了市场、玩家对于这款游戏的认可。

a1757fa28ce50df788dab0cd1a0e609c.png

在尊重和传承经典 SLG 玩法的前提下,游戏做出了不少突破:游戏构建了一个大世界,为玩家呈现更加真实、热点的游戏环境和生态;游戏融入了极具乐趣的养成模式,使得游戏策略性更强;游戏内加入了如 AR 寻宝玩法、 自定义头像等酷炫新玩法。

7d618a2782c76dec5975ee4536050b25.png

6 月 22 日,来自腾讯的游戏高级工程师肖程祺受邀出席了 Cocos 上海沙龙,向开发者分享了《乱世王者》的深度优化方案,包括《乱世王者》项目中地形处理和优化思路,深入讲解了游戏针对纹理内存优化的解决方案,并分享了项目对引擎渲染层所做的一些优化。

27fb79d7bad0aea5372b51629c2c08f3.png

肖程祺

在获得程祺同意后,Cocos 将其优化方案整理成文,同更多开发者进行分享,具体内容如下:

《乱世王者》深度优化方案分享

腾讯 肖程祺

《乱世王者》是基于 Cocos2d-x 开发的一款战争策略类游戏,需要在游戏玩法创新的同时,在美术品质和性能方面也做出突破。

一、SLG 地图的微创新和优

美术上想要增加细节表现力,让地形的细节更加丰富,同时需要增加 3D 透视的感觉。

实现成果:

ce4ae4a52e39e4ac9f7c358c237a40ed.png

1、丰富的细节

地形细节丰富的代价:

  • 资源量膨胀,地形纹理是原来的5倍。

  • 地形类型新增:沙漠,雪地,每个地形的变化增加。

tile 数量从 100 块左右提升到 500 多块。

6b56341eb1ce671aa3fad55a93809ace.png

渲染压力提升,渲染层数从 2 层变 5 层,拖动地图的时候重新组织数据的开销增加。

6efb011c027bee4017f6124e2b528073.png

面临的问题有:

  • 内存增长:纹理扩大了 5 倍

  • 地图层数增加后,加载和拖动地图更新的效率成倍降低

  • 贴图数量增加后,需要自己去实现 batch

我们的优化方案:

(1)提升贴图的利用率,减少地图纹理的内存

936e43ca65dca558e650d9a44a0460a0.png

重新排列 tile,贴图利用率从 50%提升到 85%

 效果:

e2a8170ec3613b15a8c52318f54717aa.png

5 张贴图最终变成 3 张

(2)建立更高效的数据组织,提升加载效率

地图数据离线处理后,以 protobuff 的数据格式存储,并使用 zstd 无损压缩进行处理,加载速度和大小都得到保证。

e61caa23d484eb4fb6d733d987b1e19f.png

(3)合并地图批次,减少不必要的顶点数据

每一层地图的都根据 TextureID 排序后绘制,由于顶点和 UV 数据已经存储在 VBO 里面,只需要根据裁剪结果修改 indexbuffer 即可。5 层一共 3 张贴图,意味着 drawcall 数量不会超过 15 个。

48726604512f1fd466cb287c5ef33493.png

2、3D 透视关系效果   

 (1)处理3D透视关系

  • 场景用 3D 相机绘制

  • 地图上的物体“站”起来

3cd77a6079a6f57c737ef5eb64274166.png

所有物件绕x轴旋转

至垂直于摄像机的fov中线的角度

(2)解决大物件的视角偏差

边缘位移:

04f341859bc9452dbd43b7ba7382007e.png

对于皇城和虎牢关这种比较“宽大”建筑单位,在拖动大地图的过程中会出现边缘位移的现象,这个效果也是非常影响美术表现的。

我想到的解决方案是,将大的建筑单位拆分为多个部件,并对每个部件分别作 billboard 处理。

以皇城为例,考虑到部件之间的关联性,使用了如下的拆分方案,可以看到边缘位移问题得到了很好的解决。

713570c5532a6ef06a1eb5c1b6e9b921.png

(3)解决 3D 物体的透视带来的偏差

为了表现更加丰富的怪物细节以及更流畅的动画,美术希望直接在现有的场景中加入 3D 模型。

由于我们改用了 3D 摄像机,同时大地图场景单位都是 2D 资源,加入 3D 模型后两者的透视效果不一致。

22c067389749de54b924d251fb1548be.png

在透视相机下,左右移动相机透视问题严重

容易想到的解决方案:先将 3D 模型按照指定角度渲染到 RT 上,再将 RT 上的纹理和其他 2D 元素一样渲染到场景中。但是 Cocos2d-x 对多照相机和多渲染路径的支持不够友好,这种方案需要对引擎作比较大的改造,而且会增加更多的显存占用。

我们采用的是第二个方案:在每帧绘制 3D 模型前,计算出其缩放和位移,然后再使用正投影照相机参数绘制 3D 模型到屏幕。整个过程只需要一次绘制,没有额外的纹理占用,而且对引擎的改造也是最小的。

5be0998effe97989271ae03eca0e4270.png

渲染 3D 物体前自己计算正交投影矩阵

上述这些效果提高了《乱世王者》大地图的美术品质,与同类 SLG 游戏对比,我们游戏获得了更多的关注。

二、纹理内存的深度优化

《乱世王者》内存中资源的大致占比为:

480325472ebfb56bccbec84ca8f1ca50.png

用 4 步搞定内存大户:纹理

  • SmashTexture

  • FontTexture

  • 压缩纹理的优化

  • Texture Pool

1、Smash Texture 

Smash Texture 解决的问题:

  • UI 制作过程中需要使用 atlas 来尽可能合并渲染批次

  • 因为使用 atlas 需要一套规范避免一个界面加载过多的 atlas(维护成本很高)

  • 一旦出现一个元素多次重复出现且用到多张不同的纹理,需要额外的机制去避免 drawcall 爆炸般增加

  • png 使用的 deflate 压缩率不算很高,安装包体积压力山大。有些人选择使用 jpg 等有损压缩来牺牲美术品质

bec5ed2ac297eb1b960352d347e239ed.png

(1)Smash Texture Pipeline

  • 通过 tinypng 减色,增加压缩率(如果减色效果不好,则不做减色处理)

2c78645071a8af6c476a2f2e34dbc7d5.png

  • 打包成合图后,供在编辑器中使用

569cc6a062becce4c8047f3e3acc4e3b.png

  • 转换成 smash

ec2535d4a604da723b03b0f07bf6158f.png

drawcall的降低

0412eeab0139a3a77670009d9d50288e.png

未作任何其他改造的情况下,批量使用 smash texture 后,当前界面的 drawcall 从 64 降低到了35。

(2)减少 IO:Block Cache

  • 加入 Cache 机制, 达到上限时使用 LRU 算法清理,每次清理固定数量

  • 特定时机,清理 Cache,分帧清理,不卡顿

  • 回收操作只需要回收分配信息,不需要对贴图显存操作,速度快

9708753adf4a56a732fbad40db5ac088.png

现网版本用户行为上报的 cache 命中率

(75%左右)

(3)提升Smash Texture的使用率

原本 smash texture 里面的每一行是 32 像素统一高度,利用率比较低(比如说 36 像素高的图片,最后还会留下 6 像素左右的空间。填充到 32 像素高的 smash texture 行里会存在浪费),因此我们按照下图,重新划分了高度行,容纳更多的 UI 图元。

faab62ade7e1a3039b867ecf9e691b5b.png

经过优化,smash texture 的使用率可以从 80%提升到 90%。

2b7b9bc1f0abdfe8707eec2064035e0b.png

(4)总结 Smash Texture 的优缺点

优点:

  • 内存峰值可控:所有使用 smash texture 的贴图共享一张纹理

  • 增加了 UI 利用 dynamic batching 自动合批的概率

  • 最大程度还原 UI 的品质

  • 相对 PNG,他有着更小的文件尺寸(zstd 压缩)

f7927b704350ab8e4aa9de6bbcf99eb3.png

缺点:

  • 对于大型背景图不太适合,容易填满。背景图需要额外拆分。

  • smash texture 目前只支持离线预处理,动态下载的图片还不支持。

2.文字系统的内存优化

  • 用一张 2048x2048 大的 A8 格式纹理解决所有字体需求,当贴图不够用的时候尝试清理整张贴图。

  • 不同的字号,字形,格式生成唯一的 key 在这张统一贴图中进行索引。 

d7bec9af34fbcd9251a7de3891a82fa1.png

提升贴图利用率:改良装箱算法

基于 maxrect 做优化,将纹理利用率提升到 95%+。

5142ffd2bcb9cbb6a251aca9eeeebd05.png

提升贴图利用率:减少字号数量

统计了文字的字号使用频率,根据字号分布,我们取了 5 个字号,其他字号向下取到最接近的预定义字号上,缩放后渲染,大于最大字号的时候则用最大字号放大后渲染。

a10457eb933883da8e11e6ac6ae39ef5.png

3.压缩纹理

压缩纹理的一些痛点:

9b0c961b70244bc28679eca26ae252c2.png

压缩纹理优化:

  • 对于 1/2 方图的 atlas,分离 pvrtc 的 rgb 和 a 通道,合并成方图后,再压缩。

517f760b7559390251a085390ceab114.png

  • 对于不符合 2 的 n 次幂的不规则的单图(背景图为主),通过计算出最小的 2 的 n 次幂包围尺寸,切分成多块来优化文件大小,解决 pvrtc 必须方图的不友好设定。

2372e95f100f89f836d34622bbe100cb.png

4.Texture Pool

  • 把所有贴图统一管理生命周期

  • 根据设备内存大小,分别设置贴图 GC 的阈值

  • 当贴图使用量超过 GC 阈值的时候,根据引用计数释放没用到的纹理

  • 添加运行时查看工具,运行时也可以查看不正确的贴图格式设定

8d5af678b37c69176b8e465f402e57be.png

内存管理的小结:

  • 所有模块必须有上限,避免随着迭代内容不断增加而持续上升

  • 避免浪费

三、解决 UI batch 的痛点

即便 Smash Texture,即便 Font 在一张纹理上,我们还是面临着一些 darwcall 明显可以优化的地方。

101b20f1b54e601142c984f71357ce65.png

期望的渲染顺序:

通过 TriangleCommand 底层的 dynamic batching,自动合并批次。

641554929ed314822cf6806fead54267.png

Cocos2d-x的默认渲染顺序:

41a1dad6e35a6418b6d5d136721f35fc.png

充分利用 TriangleCommand:

  • 将所有 Cocos2d-x 默认的控件以及自定义控件都尽可能改造成 TriangleCommand 实现,使得支持 Dynamic Batching。

  • CCProgressTimer

  • LayerColor

利用 GlobalZ 来解决合批的问题:

  • 对于 2D 元素,GlobalZ 的排序可以很好的让相同材质的物件进行 batch

  • 所以我们可以离线设置好 GlobalZ(存储在csb里面)

  • 根据遮挡关系和纹理自动计算

  • 人工设置

  • 自动递增

420099e504cde0a60251d0b9f67d2fa6.png

新的问题:

当 UI 有多层弹窗的时候,上下两层的控件由于 GlobalZ 都从 1 开始,所以会出问题。

4c56a2d68eeb3f23640bb9ec6e332e86.png

改动最小的解决方案:

1c94bdf7f9cbfc164365b759e1db752a.png

改动后的情况:

  • 解决了多层 UI 层级问题

  • 解决了同层 UI 利用 GlobalZ 能尽可能 Batch 到一起

47d36972083d293dcca093cac70fab0e.png

程祺演讲 PPT:「《乱世王者》深度优化分享

获取方式在公众号后台回复乱世王者

四、结语

程祺:Cocos2d-x 使用上手难度比较低,实际使用项目也很多,在开发的过程中也存在一些普遍的性能和优化痛点,希望这次为大家带来的经验分享,能帮大家在优化的道路上走得更加顺利。我们的腾讯天美上海 T1 工作室正在招聘 Cocos2d-x开发,对游戏开发感兴趣且有 Cocos2d-x 使用经验的朋友,欢迎加入我们,简历投递邮箱:cloudxiao@tencent.com。

C 姐:非常感谢程祺带来的分享!并祝项目更加顺利!

C 姐:Cocos 引擎一路走来,收到了很多来自用户的宝贵建议,通过不断的优化和改进,在 Cocos Creator 中,上述许多性能问题都已得到解决。包括:

  • 支持 Texture Packer 的 Polygon outline 裁剪,使用 Polygon outline 裁剪后的图集将对每个小图按透明区域精确裁剪为不规则的多边形,将达到类似 Smash Texture 节省图片空间的效果,对渲染性能也有一定提升。该功能无需在 Creator 中进行额外操作,导入图集后即可自动开启。

  • 从 Cocos Creator 2.0.9 开始,支持将 Label 设为 CHAR 模式,即可实现类似的优化方案。能够以“字”为单位将文本缓存到全局共享的位图中,相同字体样式和字号的每个字符将在全局共享一份缓存。提升纹理利用率的同时,也大大提升了文本刷新时的性能。详见文档[文本缓存类型]

  • 从 Cocos Creator 2.1 开始,集成了压缩纹理支持,编辑器可设置不同平台所需格式,构建时将会自动进行压缩,支持 etc/pvr 的 alpha 通道分离。详见文档[压缩纹理]

  • 从 Cocos Creator 2.0 开始,默认会在原生和 Web 平台上启用动态合图,该功能支持运行时根据渲染的先后顺序动态对纹理进行合并,降低 drawcall,用户无需对 z 进行手动指定。当 Label 启用了 BITMAP 模式后,会同时进入合批。详见文档[动态合图]

参考文档:

[文本缓存类型]

https://docs.cocos.com/creator/2.1/manual/zh/components/label.html#%E6%96%87%E6%9C%AC%E7%BC%93%E5%AD%98%E7%B1%BB%E5%9E%8B%EF%BC%88cache-mode%EF%BC%89

[压缩纹理]

https://docs.cocos.com/creator/2.1/manual/zh/asset-workflow/compress-texture.html

[动态合图]

https://docs.cocos.com/creator/manual/zh/advanced-topics/dynamic-atlas.html

2293afc6cb7fd854a682655c483c44db.png

Cocos 技术派 | 实时竞技小游戏技术分享

Cocos 技术派 |《野蛮人大作战》从开发到上线

Cocos 技术派 | Cocos Creator 2.0 摄像机的灵活运用

Cocos 技术派 | 重度小游戏《三国封魔传》技术实现方案

Cocos 技术派 | 3D 人物渲染详细教程

《我飞刀玩得贼6》性能优化案例分享

Cocos Creator v2.1.1 新增 3D 场景编辑

互动类游戏潜力大,这款插件让你1小时创造作品

创意小游戏专访 | 《蛇它虫》

创意小游戏专访 | 《五子大作战》

创意小游戏专访 | 《甜蜜糖果屋》

点击

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值