高频面试题之你做过哪些优化?以2d游戏为例。

高频面试题之你做过哪些优化?-以2d游戏为例。

背景

  • 在游戏的面试中,经常被问的一个问题,你有没有做过什么优化?我觉得大部分人几乎都没有做过优化,虽然我也做了7年多的H5游戏,我也没怎么做过优化,我一般都诚实回答没有做过什么优化。后经前同事提醒,不能这么实诚。如果实在没有做过什么优化,不妨可以从项目的一些规范出发来回答,以下便是一下规范的讨论。

白鹭引擎的遗产

  • 虽然白鹭引擎已经凉凉了,但是白鹭之前的技术总监王泽在18年的一篇分享仍具参考意义(温馨提醒,18年已经是7年前了)。这篇文章的题目是《白鹭引擎王泽:重度H5游戏性能优化技巧》(以下简称《优化技巧》),来自白鹭引擎的一个沙龙分享,并且可以在任何一个搜索引擎搜索得到。

  • 本文部分优化点来自上述文章,但会有例子延申。

游戏的开销

  • 一个游戏的开销可以分为js逻辑开销和渲染开销。

js逻辑开销过大以及优化举例

  • js逻辑开销过大可能是由以下问题引起的:
  1. 同一帧进行了大量的计算。可能的优化方法有:

    • 随机延后+节流。例如升级会触发很多系统红点的检测,这样可以设置一个机制,随机延迟0.2到0.6秒(随机延后),暂时取0.3秒,那么在这0.3秒内,无论触发多少次,也只有0.3秒这个节点生效,这在web前端是常用的优化技巧,叫做节流。随机延后的思想也可以用在登录或跨天的时候。对于这个,你可以包装成,原来的红点系统,在数据变化的时候马上就会进行检测,当升级的时候,会卡顿一下,我通过使用随机延后+节流的方法,成功解决了这个卡顿问题。

    • web前端常用的优化技巧还有一个叫防抖,有兴趣的也可以了解一下可以用在什么地方。(我曾经用到的一个场景是,游戏要上h5网页渠道的时候,一般都需要监听resize事件,但浏览器或document的resize事件是频繁触发的,这个时候,可以先统一监听resize事件,然后利用防抖的方法,延迟一段时间之后再触发一个新的自定义的事件。)

    • 分帧。对于同一帧会创建大量对象的操作,比如有列表的界面。列表的item就可以分帧创建。

    • 更具体的卡顿,可以借助谷■浏览器的performance工具进行调试。

  2. 大量创建对象。可能的优化方法有:

    • 像第一点所说的,使用分帧的技术,对象创建的开销远远大于对象计算的开销。

    • 使用对象池。对象创建会导致■■回收,而■■回收会导致游戏不定期卡顿,如《优化技巧》一文所说。

  3. 以内存换cpu的策略。

    • 例如:背包的数据通常是以id为key,值为道具数据的对象。但如果你的游戏,也经常需要按类型获取道具的数组,那么,也可以另存一个对象,以类型为key,然后值为一个数组,数组包含所有对应类型的道具数据。有了这个新对象,那么当你需要获取某一类型道具数组的时候,就不需要遍历背包对象了。

    • 在上面背包的例子中,当道具增加或删除的时候,需要维护新的key的对象,这也是大家要衡量的东西。

    • 同样的策略也适用一些配置表,某些配置表可能某些时候需要以a为key访问,另外一些时候则需要以b为key访问,那么就可以同时存在两份分别以a为key或b为key的配置的对象。如果不这么做的话,那么在需要以b为key访问的时候,就需要遍历以a为key的配置了。

渲染开销过大以及优化举例

  • 渲染开销过大可能是由以下问题引起的:
  1. 渲染内容过多。可能的优化方法:

    • 屏幕外的内容可以设置隐藏。

    • 打开一些全屏窗口的时候,也可以把游戏的地图层、实体层和主界面菜单隐藏了。

    • 列表使用虚拟列表。

  2. 渲染方式不对。可能的优化方法:

    • 同一个图集的Sprite尽量相邻放置,原理是同一个材质和纹理的Sprite,可以一次性提交多个顶点数据。

    • 对于场景中实体的血条和阴影,可以让血条同时在同一层,阴影同时在一层,正如《优化技巧》中提到的那样,血条,阴影的坐标可以实时与实体同步。

    • 如果界面上面的文字比较少,可以考虑使用美术字替代。

    • 尽量少用蒙版。蒙版需要用到stencil test或clip test,也会打断渲染合批

    • 允许图片资源的冗余。在公共图集的某些资源,例如红点和底板,也允许在一些系统把同样的红点和底板打进图集。红点的分辨率可能是20x20,底板的分辨率可能是30x30,增加的内存不会太多,但是对于降低drawcall来说,效果是非常明显的,尤其是界面有列表的时候,非常值得。例如

其他

  • 在《白鹭引擎王泽:重度H5游戏性能优化技巧》一文中还提到,对骨骼动画使用缓存,优化骨骼开销。这个优化,还真的不知道怎么操作。AI给出的一个答案如下,但这不是本来就会自动完成的吗?

最后祝不在广州的朋友都能顺利通过面试,在广州的朋友,还是先祝你们不那么顺利吧,可以把机会也留给我试试,哈哈。

下一篇,可能会对商店售卖的一些减少dc方案进行个人的探讨。

作者qq/wx:408293635

ps,作者正在寻找base广州的机会

12赞

内存优化感觉还是很有必要的

内存这块,我觉得,对于2d游戏来说,内存的压力其实来自于纹理资源的,只要你的项目能够及时的释放掉不需要纹理资源,一般不会有什么问题。
这里说的及时并不是立刻释放,因为有些界面可能会被频繁打开和关闭,频繁的释放资源和加载图片资源,再生成gpu纹理的开销也不少,也会让手机发热严重。
应该要设计一种延时机制,同时也可以通过监测纹理的内存占用,通过多种因素的结合,设计出符合自己项目的释放资源策略。

是的呢,一些通过远程加载的纹理,如果图片过大过多,内存占用非常高,就需要设计加载逻辑和资源释放逻辑了。还有频繁调用 localStorage (比如一帧调用上万次),会出现明显的掉帧卡顿,甚至卡死。就需要你上面说的延迟处理,使用缓存的策略了。