先做减法,再做加法。
整理 / 林致
6月25日,腾讯公司举办了一场微信小游戏开发者盛会,乐元素公司的祥一在会上详细阐述了《开心消消乐》成功转型至小游戏平台的整个过程。
这款游戏自十年前上线以来,其月活跃用户数始终维持在1.3亿以上,并且在畅销榜单上保持着稳定的地位。进入2024年,随着微信小游戏的正式推出,该游戏迅速吸引了众多玩家的目光。
在这场技术迁移过程中,他们面临的最大挑战在于:如何在性能有限的小游戏环境中,确保原本在手机App上运行的复杂动画以及上万关卡内容能够流畅运行?经过深思熟虑,团队采用了“先简化,后优化”的策略,从削减不必要的功能开始,再到并行推进各项开发任务,他们竟然在短短100天内成功实现了上线目标。
以下为分享内容整理,为方便阅读,内容有所调整。
大家好,我是祥一,来自乐元素公司。今天,我将向大家详细讲述《开心消消乐》团队如何将APP手游成功转型为小游戏的整个迁移过程。
《开心消消乐》这款游戏家喻户晓,众多在座的朋友以及他们的亲朋好友们,想必都曾亲身体验过这款游戏。
2014年,我们的游戏在iOS平台上正式推出,时至今日,游戏运营已走过超过11个春秋。在此期间,我们陆续推出了安卓版本,并于2024年成功推出了鸿蒙版本。截至目前,游戏的主线关卡数量已突破一万关,且每周都会新增30个以上的关卡。
基于这款App游戏所拥有的众多关卡内容和丰富多样的玩法,若将其移植至小游戏平台,所需投入的劳动量无疑是巨大的。这主要是因为游戏自诞生以来累积了大量的功能、活动和代码,同时还要确保与现有平台实现兼容,因此整个项目的难度相对较高。
我们面临的主要难题在于,需要将App端的全套技术体系成功转移到小游戏平台。
App此前是基于加Lua进行开发的,如今面临向小游戏平台的迁移任务,然而小游戏却只能在App内置的GS环境中运行。若在小游戏内继续采用Lua进行执行,便会产生一个Lua虚拟机嵌套在另一个虚拟机中的情形。尽管如此,我们无法规避这一模式,否则App和小游戏两个开发方向将不得不各自独立编写代码,这将显著增加开发成本。
因此,在小游戏平台,我们选定的技术架构是以某种方式构建的,通过某种方式来生成代码,同时保持业务处理逻辑在 Lua 环境下执行。然而,在这种配置下,小游戏中 Lua 的执行速度可能会略显逊色。
在项目初期,我们精心筛选出了最关键的部分,并确定了最小的发布规模。在制作首个版本时,主线的关卡数量设定为1005关,随后经过调整,最终增至2010关。
此外,《开心消消乐》作为一款现正运营中的游戏,我们期望为用户带来连贯的游玩感受。不论是于应用内还是小游戏环节中,我们都力求确保用户账号的互联互通,保持数据资产的统一性,以及让用户在两个平台上都能享受到参与活动、获取道具与素材资源的便利。
所以,我们必须构建一个全面的框架,其中应包括一系列基础功能、必备的道具以及支付手段的兼容性。
此外,我们期望在小游戏方面也能确保玩家获得优质的体验,不仅帧率要符合标准,而且启动速度也必须满足要求。
面对我们而言,最大的挑战在于时间的紧迫性极强。当我们接到任务时,仅有大约三个月的时间来完成系统的上线工作,因此当时所承受的时间压力极为沉重。
小游戏的运行效率问题不容忽视,这主要源于其运行于GS环境中,导致其效率本身已经大幅降低。官方公布的测试数据以及我们自行进行的计算均显示,其可用性能大约仅为Net5的三分之一,并且由于无法运用多线程技术,我们在性能提升方面遭遇了极大的困难。
迁移工作的第一个步骤是先确认我们的最小验证集。
《开心消消乐》的核心游戏机制在于闯关,一旦闯关环节出现障碍,后续任务将难以推进。界面展示主要依赖动画效果,若其运行效率低下,几乎所有的后续方案都将面临重做。在最小验证集测试通过后,我们着手进行业务逻辑的迁移、小游戏平台功能的接入、测试以及优化工作,最终实现了上线,并对功能和游戏玩法进行了迭代和改进。
前期的最小验证集对我们来说是挑战最大的一部分。
我们的这款游戏App是在原有基础上进行开发的,当初为了满足产品需求并迅速完成上线验证,功能开发进展顺利。然而,经过这几年的运营,我们逐渐意识到,产品在表现力、玩法内容和3D建模等方面出现了更多新的需求。
因此,我们之前便着手进行了相应的迁移工作。此次迁移之际,我们趁机将发行小游戏时版本导出的小游戏设定为首要任务。然而,在客户端方面,我们仍需确认其运行时是否能在相应平台上顺畅运行。
幸运的是,经过去除了联网功能后的版本,在相应版本中,高端机型能够实现大约50帧的流畅运行,而低端机型也能达到十几帧,这一结果让我们看到了一线希望,至少在运行方面并未出现重大问题。
在此次测试中,我们亦需对运行效果进行确认。我们选取了一个具有代表性的动画场景进行测试,其中包含了众多动画元素,结果显示运行效率大体符合标准,然而,仍有相当数量的动作环节有待进一步改进。
工作流程的目标和整体架构已经明确,后续的关键任务是对代码和资源进行转移——这些内容必须被转移至指定平台。
在小游戏领域,所有的动态动作加载均采用异步方式进行,然而在性能优越的App应用中,多数加载操作则采取同步模式。由于这种差异,小游戏中的加载方式在App端无法直接应用,因此,App端的基础底层架构在文件和资源加载方面必须进行相应的迁移和调整。
我们经过对配置文件和 Lua 代码的深入剖析,对所引用的资源进行了智能化的归类,依据不同的障碍名称和关卡段落,将这些资源分配至相应的不同类别,同时实现了相关文档的自动化生成。
通过以上数个阶段,我们大体上实现了一个在客户端以及Web平台都能顺畅运行的完整版本。接下来,我们将着手解决不同平台之间的差异以及兼容性问题。
在小型游戏平台上,我们面临的首要任务是首次整合众多第三方接口,同时亦需与小程序的API及开发功能实现对接,确保能够实现用户登录、支付以及广告展示等关键功能。
启动后,我们不可避免地遭遇了一系列问题,这些问题主要涉及运行缓慢、设备过热、画面刷新率偏低、内存资源短缺引发的系统崩溃或错误提示,以及效果未能达到预期等方面。
最小验证集阶段对美术资源压缩率要求极高,技术层面需确保其运行流畅且可见,但美术团队对效果方面肯定难以接受。故此,后期工作需在美术资源压缩纹理上适度加强,逐步提升视觉效果。同时,纹理品质等方面需与美术团队协作,共同在效果与资源之间寻求平衡,力求实现既流畅运行又满足视觉效果的目标。
接下来,我们将详细阐述众多提升策略,然而,这些策略的实施需建立在可衡量的标准之上。唯有当性能数据被量化,我们才能有据可依,对后续的优化措施、实施步骤及其成效进行评估。
我们普遍对所采用的性能评估软件较为熟悉,诸如 、 等等,这些软件功能齐全,也是我们作出选择的重要因素之一。
微信开发者工具配备了成熟的辅助工具,包括特定的工具和功能,这些工具能够增加CPU的运行压力,从而使得我们更便捷地识别出CPU层面的问题。
即便在开发机上的运行表现再出色、再顺畅,这也并不能等同于用户实际使用时的体验,所以我们最关注的焦点还是真实设备上的表现效果。
将实际设备或工具生成的数据输入至该工具,导入完成后,我们观察到的恢复效果与开发设备上的呈现几乎相同,而且该工具的操作体验相当出色。
文档中以及开发者的最佳操作指南中,对小游戏的改进方法进行了详尽的列举,我们对此已逐一实施。然而,在我们看来,关键的改进主要聚焦于内存和计算这两个领域。其余的优化策略大多是对这两大要点的补充和拓展。
在小游戏领域,尤其是在微信小游戏中,iOS平台的“+”模式显得尤为重要。这一模式直接影响到我们的可用内存以及效率的提升。
在iOS的高性能模式下,微信小游戏会将其运行在一个独立的进程之中,此举使得内存分配呈现出全新的格局,从而极大地提升了内存的利用率。此外,WASM的分包技术对内存的细化效果显著;同时,降低渲染分辨率也是一种能够迅速见效的优化手段。
尽管操作简便,但针对我们初期App端设计的720像素宽渲染效果,将渲染效果调整至目标分辨率后再进行放大,这一做法在提升帧率和减少内存占用方面都表现出了显著效果。此外,在小游戏中,预加载资源和用户数据的敏感度极高,无论是其使用量还是加载速度,都极大地影响着游戏的启动时间。因此,我们应尽可能将可并行处理的操作进行并行执行,以此显著提升数据加载的速率以及系统的启动效率。
在内存优化方面,通用的手段主要是解决内存泄漏问题。
虚拟机嵌套虚拟机的架构要求对每一层内存进行严格管理,Lua与GS环境自身也可能存在内存泄露的风险。在初期移植阶段,我们优先考虑了速度,而在后续的迭代中,我们逐步解决了大量的内存泄露问题。此外,实施资源按需加载、采用压缩纹理格式、以及WASM分包等策略,对于提高加载效率、减少内存消耗都起到了显著作用。对象池的使用也能缓解 GC 的压力。
对小游戏导出的优化工程进行了众多参照式的改进,从而使得导出过程在性能方面实现了显著增强。在处理垃圾回收(GC)频率上,iOS与安卓采用了不同的策略。微信小游戏在(JS)层面会每隔10秒钟自动执行一次GC,然而在Lua环境中,我们最初并未设定定时的GC机制,这一疏忽可能导致游戏出现大范围掉落或关卡运行中的内存问题。随后,我们在iOS平台上实施了周期性的垃圾回收机制;而在系统上,鉴于性能较低的设备难以承受频繁的垃圾回收,我们决定仅在每局游戏结束后执行一次垃圾回收操作。
WASM的分包技术在内存优化方面具有显著成效。在总计约11万个函数中,首包包含了大约1.8万个函数。在未进行压缩且包含符号表的情况下,包的大小约为55MB。经过分包处理,首包的体积降至约15.8MB,而分包文件的大小约为40MB。值得注意的是,这两者在未包含符号表的情况下,其容量几乎与未进行分包时的体积相当。拆分后,代码的总量却有所上升,这主要是因为在过程中加入了众多关联检测、参数配置以及异常管理等内容,进而造成了代码的重复。
此外,采用 br 压缩技术能显著减小首包文件大小,将15.8MB压缩至3.4MB。分包技术的最大优势是能大幅减少内存消耗。根据官方文档,GS代码大约1MB对应10MB的内存占用,而40MB的分包可以减少约三分之二的GS内存占用,从而为美术素材等资源腾出更多空间,显著提升效果。
在计算优化方面,我们重点解决了几个问题。
小游戏的性能大约相当于 Net5 的三分之一,若计算优化处理不当,将面临巨大的性能压力。我们移除了众多 try- 函数,这是因为经过 WASM 转换后,代码体积显著增大,且检查成本较高。此外,虚拟机的嵌套结构使得参数传递过程中出现了多层装箱和拆箱,当参数数量较多或参数量大时,这种影响尤为显著。
我们对小游戏的补帧机制进行了优化。《开心消消乐》的操作流程涵盖了逻辑计算与图形渲染两部分。逻辑层面的帧率设定为每秒30帧,一旦在大型掉落场景中单个帧的计算耗时过长,便可能导致游戏出现卡顿现象。如果这种卡顿持续不断,用户的体验便会如同置身于“子弹时间”般的不适。在移动应用端,大型掉落通常只会影响1到2帧,玩家很快就能恢复正常。然而,在小游戏版本中,由于无法进行帧追赶,这种卡顿很可能会引发连锁反应。
因此,我们对补帧策略进行了优化,仅追踪部分帧,并整合了可合并的逻辑,以降低雪崩效应的发生。此外,我们还对 Lua-C# 的参数传递和 JS 接口调用进行了优化,着重改进了 Lua 代码的业务逻辑部分,旨在克服 Lua 执行效率的不足。
在动画优化过程中,我们始终聚焦于两大关键议题:一是计算资源的使用效率,二是内存的消耗情况。
《开心消消乐》游戏关卡中,动画是其核心呈现方式,绝大多数的关卡障碍和可爱的小动物均采用了动画设计。在移动应用平台上,动画的呈现效果相当出色,且优化潜力巨大;然而,在小型游戏设备上,此类动画却带来了显著的计算负担和内存消耗问题。
在内存处理上,我们实施了降低顶点数量、削减网格数量的策略,旨在减轻计算压力。此外,当动画进入静止阶段后,我们将其转换成静态图像,这样做既减少了内存的消耗,也降低了计算成本。对于能够被替换的部分,我们力求进行替换;而对于那些不能替换的动态元素,我们则通过减少帧数或抽取帧数来降低成本。
另一个关键在于消除或改进剪辑效果。在应用程序中,美术人员为了增强表现力广泛采用了剪辑技术,然而在小游戏平台上这一功能并未得到充分支持。于是,我们与美术团队携手合作,移除了那些多余的剪辑,并对那些必须保留的剪辑实施了美术与技术的双重优化,这包括降低内存占用以及提升使用效能。
此外,我们采用了 Mesh 动画技术,在动画计算阶段预先对三角形网格进行计算并保存,运行时直接调用静态的 Mesh 资源,以此换取内存空间来提升 CPU 性能。然而,这种方法在无法预先确定骨骼位置或需与业务逻辑紧密配合的场合,如持续展示进度指示的星星瓶等,则无法应用。在这些场景下,我们同样进行了优化处理,将连续的进度分解为十个具体阶段,这样做有助于减轻计算负担,而且实际效果与预期目标基本相符。
针对 API 的优化层面,小游戏的文件处理和API调用效率存在局限,同时,其嵌套的虚拟机架构也带来了额外的成本。在应用端,为了实现崩溃后的状态恢复,玩家每次进行操作时都必须将状态信息保存至磁盘。这种现象在小游戏平台上表现为明显的响应迟缓,鉴于此,我们决定取消小游戏平台上的高频次文件操作。
音效的播放同样受到了相应的约束,因此我们对音乐播放功能进行了简化,移除了那些非必要的代码,以此达到提高效率和减少代码量的目的。同时,对于震动效果,我们也进行了优化处理,在游戏中仅保留了高、中、低三个震动级别,去除了曲线控制功能,并通过封装函数的方式,将震动所需的时间从原先的20毫秒以上缩短至几毫秒以内。
Lua代码的优化至关重要。在对比了文本模式后,我们发现其对加载效率的影响并不显著,然而,文本模式的代码体积却更为紧凑,且内存消耗更少。尽管在查错时其可读性有所降低,但通过结合字节码与文本代码的混合使用,我们能够在维持性能的同时,确保在定位问题时能够获取到全面的信息。
经过一系列的改进措施,我们成功在约100天的时间里完成了系统迁移,并在8月份启动了测试工作。在此过程中,我们没有引入新的业务逻辑,只是将原有功能从原系统迁移到了小游戏平台,这项工作的繁重程度由此可见一斑。这一切的成就,离不开团队内部各部门的紧密协作以及多任务同时推进的高效运作。
总结经验,我们的核心做法包括:
先进行减法操作,随后进行加法。首要任务是删除所有非必要元素,并检验最基本的功能结构。一旦这一基础得到确认,便可以逐步引入新的功能。如果在技术选择上最初就误入歧途,所付出的代价将会极其巨大。
力求各项任务同时推进,并全面开展相应的辅助工作以促进开发速度的提升。例如,对引擎进行优化、实现API的接入、改进渲染效果、完成业务系统的迁移、更新美术资源以及优化产品设计等任务都可以同步进行。唯有将所有环节同步进行,才能有效缩短整个项目的周期。
对产品进行短期与长期规划,并据此拟定切实可行的开发方案。《开心消消乐》自运营十年以来,其内容丰富,故需精心策划,明确哪些内容适合迁移至小游戏平台,以规避不必要的开发工作。
与公司内外部的专业人士保持沟通,以便迅速获得高效解决方案。在项目实施期间,我们受到了微信小游戏开发团队及其他团队的大力协助,这极大地促进了方案的实施与落地。