车钟日是一家核心团队在卡牌品类有着超过8年积累的开发商,旗下以《新斗罗大陆》为代表的系列产品累积流水破40亿,用户总数4000万+。
在多年开发过程中,团队也积累了一套游戏优化方案。今天我将基于团队一款全新的卡牌游戏「omniheros」,和大家分享几个行之有效的卡牌游戏优化方法,以及自己的一些心得。这款游戏目前正在测试阶段,敬请期待!
业务层只需要关心每个子节点的判断逻辑,何时刷新,刷新时是否需要传参数即可。
104的 check 方法里有一个固定传参1,这个参数在每次判断的时候都会传入。
当105在 func(2) 的判断下从未激活变成了激活,会将状态传给101,101有一个激活状态的子节点,不需要管其他子节点,自己也会变成激活, 并将激活状态传给100,而使得100也变成了激活。
当107在 func() 的判断下变成了未激活,会将状态传给103,103只是根据107的未激活并不能直接决定自己的激活状态,它需要检查其他子节点的状态,所以需要检查108的激活状态,若108是激活的,则自己激活;若108未激活,则自己未激活,并将状态传给100。
如果107检查前和检查后的状态有变化则会将状态传给父节点103,如果没有变化则不用向父节点传递。
104,105需要相同的动态参数 e1,即101的子节点需要相同的动态参数。
107需要动态参数 g1,108需要动态参数 g2,即103的子节点需要不同的动态参数。
在动态参数的树结构里,对于叶节点107或者105,没法确定其他兄弟叶节点的参数是否与自己一致,所以这里需要遵循一个原则,只有激活状态可以传给父节点,动态参数不能传。
对于103,子节点需要不同动态参数,所以对于107和108的刷新只能选择各自分别刷新,然后同时将状态传给103。
对于101,子节点需要相同动态参数,所以对于104和105的刷新可以选择各自分别刷新,也可以选择刷新101并且将动态参数传给子节点104和105。
因为列表每个元素不固定,元素数量不固定,所以没法绑定红点 id,即列表的红点处理目前选择自己判断,不走树结构。
id 为红点对应 id,有些 id 可能为虚拟 id,在 UI 里没有对应界面。
可以设置为1后端判断,因为在登录游戏到主城过程里,部分功能是不需要拉取对应的消息的,那这部分的红点激活状态没法通过数据的逻辑判断,只能靠服务器判断之后将结果返回,等到进入对应功能拉取到该功能信息以后,才接管为绑定的检查方法判断。
function_id 为功能 id,用于红点功能开启判断,减少无效的判断耗时。
priority 优先级,在 update_type 为1时,可以设置优先级让比较简单的判断逻辑先判断,减少后端判断耗时。
show_type 为显示类型,配合显示优先级使用,优先级越高先显示,可自由设置每个显示类型对应的显示优先级:
wwise 是一款针对游戏开发的综合音频中间件解决方案,可创建精密、丰富的互动音频。它由紧密集成的设计工具和声音引擎构成,可让声音设计师和程序员在更短的时间内更经济地完成令人震憾的音频。
fmod 引擎是一种跨平台的音频引擎,可以在 windows,安卓,iOS,web 等开发平台使用。可设置多个通道,对单个通道进行变速,例如游戏只希望对技能音效进行变速。
需要 OpenGL ES3.0 以上才支持,根据调查,我们发现海外有99.2%的玩家手机是支持,不支持率仅占0.8%,而且这种情况在国内是更为乐观的。针对这部分玩家,我们可以选择抛弃,也可以选择做软解支持一下,只是这软解会比较慢。
Creator 2.4 需要修改 C++ 底层逻辑来加载 ASTC,这部分网上是有现成例子的。
我们了解过 ASTC 后,发现这种纹理其实是有很多分块压缩方式。如图,分块越大,压缩倍率越高,当然图片的质量会越低,那么我们应该如何选择分块呢?
左边的图片细节比较多,颜色比较丰富,选择 6x6 的方块才能有比较好的显示效果,而右边的图片色彩较为单一,只需要选择 10x10 甚至 10x12 都可以,如果我们按照文件夹的方式,对右图进行 6x6,其实会是压缩倍率不够造成浪费的,所以对文件夹进行白名单方式是比较难对单个图片找到最合适的分块方案!对此我们提出了一个较为准确的一个方案——相似度匹配的方案。
这样主要是比较原图与压缩图的相似度,找到我们认为比较合适的压缩比。那么如何去实现这相似度匹配呢,这里我们提供了一个相似度匹配算法仅供参考。
每一块的每个像素 rgb 值的差值,乘以该像素的透明度,求出差值 rgb 的亮度。
如图,A 的分块颜色信息较多,B 的颜色较为单一,压缩后A的差异性是所有方块最大的,我们就会选择 A 作为整个图片的差异性,目的是为了显示效果更加准确,优先保美术品质。
获取手机设备信息(手机型号、CPU 最大频率、GPU 频率、最大内存、剩余外存、核心数)。
这种分级解决了大部分表现效果对手机硬件的匹配,但这个过程中我们观察到部分手机可能 CPU 计算能力不怎么好,但是内存比较高,所以我们做了更为细化的分级方案。
画 UI 的方式,没有非透明的剔除机制,针对这一点,一般的优化手段就是减少绘画次数,画一次就保存起来,对此很多游戏都用一种比较实用的优化方式。
然后将模糊图后面的场景都隐藏掉。利用这个思路,在此基础上可以做一些其他优化。
把需要优化的节点,如比较复杂的列表,分配到 postRender 这个分组,这样主 camera 就不会渲染列表了。
这样的目的是利用另一个相机对这个复杂的 UI 只渲染一次,让主相机对这个复杂 UI 的渲染转变成对一张贴图的渲染,这样的方式结果就是:
效率提升了很多,如下图,drawcall 减少了很多,fps 也提升比较大。
下图是一个大地图 UI,手机显示的部分只有中间蓝色框那么大,但是地图却超出了很多,且有多个分层和特效,而且会多复制一份作为循环移动的衔接,所以加载这么一个大地图 UI 需要的时间不少,比较差的机型打开这个界面必然会出现黑屏时间,为了解决这个黑屏时间,我们也做了一个比较好的优化。
等大地图加载完成,再把新的渲染场景重新截图绑定到缓存节点,放回 preload 节点。
这样利用这个缓存的截图可以有效的避免了加载黑屏时间,除了大地图,也可适用于其他加载黑屏的场景,如果觉得这个缓存截图可能会造成较大的内存开销,可以利用贴图尺寸减半的方式减少内存开销
重新打成小包,剩余资源作为小包的补包打成 zip 分包,整包 = 小包 + 分包。
游戏过程中如果用到手机里没有的资源,则立马从有所有散文件资源的服务器下载。
这个流程整体还是比较完善的,但是会有一个问题,下载分包需要时间,如果在玩游戏过程中,用到的分包里的资源,就需要从散文集列表的下载,等待下载完成才能继续进行,造成游戏的卡顿,为了优化这个问题,结合我们游戏是散文件更新方式的形式,我们在此小包基础上做了优化。
跑游戏前期,标记所有用到的资源,记录资源列表 List_small,并且这个 List_small 是有序的。
按照小包大小要求打包,把 List_small 里按顺序打进包里,直到达到小包限定大小,没有打进包里的列表重新生成一个 List_pre 作为优先下载队列。
进入游戏后首先执行正常的强制更新(对比的是 List_all 和当前线上版本资源的差异)。
游戏过程中优先下载 List_pre 里的资源,如果有用到的资源而本地没有也会立即去下载。
其他小包缺少的资源在后台下载(List_small 和当前线上版本资源缺少的部分)。
List_pre 可以按照顺序优先下载,尽量保证用到的资源能提前下载好。
其实,各种优化方向都是在原有基础上提出更高的要求,然后需要我们去大胆尝试解决方法并充分验证,最后再合理的范围内做出取舍,从而实现更好的游戏优化效果。
另外,在游戏开发中,性能方面其实有很多方面都可以有优化空间。本次选取的是我们团队积累的比较典型的几个方案,还有一些其他方案,如果小伙伴有兴趣,我们可以一起交流。
|