发布时间:2025-04-24 19:44:16 点击量:
HASH GAME - Online Skill Game GET 300
近年来,小游戏发展迅速并逐渐成为游戏公司业绩增长的新引擎之一。仅微信小游戏用户规模已达 10 亿,其中月活跃用户 5 亿。庞大的用户基数为开发者提供了广阔的市场空间。 在 2024 年 11 月 2 日的 Unity User Group 深圳站,Unity 中国引擎底层架构技术主管兼小游戏技术负责人赵亮和 Unity 中国引擎底层架构开发组长詹泽行带来分享《团结引擎小游戏开发指南》, 从实际案例的数据对比到底层优化的深入解析如何使用团结引擎 开 发加载更迅速、内容更丰富、画面更精致、运行更流畅的小游 戏。 本文为演讲全程实录, 请点击文末
文件系统,传统的 native APP 很多游戏资源放到游戏包里,或者是进入游戏之前先下载下来,后面直接读文件,都是同步操作。但是在微信小程序要进行快速启动,首包非常小,其他资源是后续通过网络进行下载,都是异步的加载,会涉及到游戏同步到异步的改造。另外关于持久化存储文件,小游戏是从 WebGL 过来,WebGL 在浏览器里是一个沙盒的环境,为了安全会限制访问设备本地的文件。所以游戏退了之后有一些想要存储的数据,必须要通过微信提供的特殊接口来存储。
Texture Manager。微信小游戏有一个比较尴尬的难点是 PC 上和手机上支持的纹理压缩格式不一样,而且没办法兼容,PC 只能使用 DXT,手机只能使用 ASTC,如果不符合这个要求就导致内存比较多,体验不好。所以 Texture Manager 首先支持的是一个纹理可以打印多套纹理压缩格式,运行时自动选择,比如 PC 上使用 DXT,手机上使用 ASTC,不会导致性能问题。 二是 Texture Manager 会管理纹理的生命周期,纹理依旧存活但是没有使用的情况下,会把纹理的数据从 GPU 上踢下来,节省 GPU 的显存。 Texture Manager 也会在打包时做纹理重映射,我们发现不合理的 AB 组织结构或加载方式导致纹理重复造成浪费,Texture Manager 会进行重新处理,相同的纹理只会出现一张,不会重复。
Wasm 瘦身。Wasm 大小直接关系到编译的内存,如果 Wasm 是微压缩状态,10MB 的 Wasm 大概占运行时内存 70-100M,大概是 7-10 倍。我们推荐要对 WASM 瘦身,一般推荐上线游戏首包 Wasm 不要超过 20MB,这是比较上限的位置。在 AB 加载这边也经常看到用户踩到一些坑,使用 Unity 默认的 Web request 下载,导致有一部分缓存长期驻留在内存里没有清理,这里推荐直接把下载机制换成微信的WxAssetBundle,可以自动把内存没有使用的踢掉。
Skinning的介绍,GPU-Vertex Shader和GPU-Transform Feedback是在团结上新支持的两个选项。开启方式也非常简单,Transform Feedback 直接打开就好了,Vertex Shader 就需要在 shader 代码中改一行代码。右上角的图是需要修改的操作,加入一行代码,下面的图是修改完代码,引擎的编译器就自动处理成下面的结构,自动支持 GPU Skinning。
SIMD 支持,目前引擎大多使用的还是标量运算,对一些性能不是很友好。所以我们在 Math 库上支持了 Wasm 的 SIMD。为什么选择 Math 库呢?因为引擎里包括 transform、动画、粒子等很多都依赖 Math 库,这样可以让引擎整个都能享受到 SIMD 优化的好处。需要注意的是 SIMD 在 iOS 上是 16.4 版本上才支持,如果微信小游戏用户群覆盖广,可能这个功能暂时还不能用上。
如果是用 InstantiateAsync 异步就是把这两步拆分到两帧去做完。如果它是在 native 平台,可以通过 job 加速对象的构建。但是微信小游戏的环境比较特殊,它是单线程, JobSystem 无法加速,另外上传的资源没有办法放在另外一个线程,所以 Integration 这步耗时会相对更长。所以这里针对这一步做了一些拆分,让它可以在 integration 这步分成更多帧执行。拆分的过程中,会确保子任务执行的顺序和原来一模一样,不会出现顺序的问题。
GPU Instancing的支持。这个 feature 我们预期在团结的 1.4.0 即 2024 年 12 月底可以发布出去。右侧有一个 profiler 的结果,打开了 GPU Instancing 之后,我们的 Setpass 数是差不多的,但是 Drawcall 数会大幅降低。假如不开 Instancing,对于有些场景 instance 数量特别多的情况下,drawcall 有可能到 5000 以上,打开之后可以通过 Instance 的方式绘制,这样 Drawcall 的数量降幅会非常明显,变成之前六分之一的样子。无论是 iPhone,还是安卓,高端和低端设备上都能看到 FPS 有明显的提升。
对 C# 编译器我们也做了优化。一是做更好的增量分包,比如小游戏发了一个包,隔一段时间对代码做了一个小的改动,需要再更新一个版本。这个时候我们不希望重新做一次采集分包的过程,因为采集分包比较耗时,而是想利用第一次采集的结果。这意味着做少量代码改动时重新编译生成的 WASM 里面的函数签名需要很稳定,这样原来采集的信息才是有效的。Unity 原本用的 Rosyln 编译生成出来的函数名不是很稳定,主要是 Lambda 的表达式里有一个 MethodOrdinal,编译器对于一个函数假如有重载,在里面会通过数字标识不同的重载,这个数字生成的时候不稳定,导致可能代码压根没有改动,但是两次编译函数生成的签名不一样,导致采集 broke,这一块我们打算修掉。
第二是,用 foreach 遍历 List,跟不用 foreach 来遍历 List,会发现这两个生成的 Wasm 代码差异非常大。发现 foreach 在 Rosyln 编译的时候会进行展开,里面会增加一个 try-catch。假如自己从 list 拿一个 enumerator 进行一次循环的话,生成的 WASM 大概只有 100 多条,但是如果套了 Try-catch 之后,再调取 disposable,就会有 500 多个 instruction。当一个游戏里大量使用 Foreach,会导致带来很多 Wasm 的体积膨胀及运行时内存增加。Try-catch 很多时候发现它不是必需的,所以我们准备在 Rosyln 的编译器里面给它一个选项,当你选择不需要 try-catch 的时候就可以优化掉。
动画压缩,主要是集成 ACL 库,它有更高的压缩比。用一个 animation clip 进行对比,不开启压缩占了 327K,原本通过 Keyframe Reduction 或者是 Optimal 的方式能降到 62K,用了 ACL 之后能够降到更低,是 Optimal 的六分之一,只有 10.3K。这对于小游戏特别有用,让打包的 animation clip 资产变小,使得加载更快,包体更小,同时运行时内存也有相应的降低。ACL 对于 animation clip 的 sample 也会更快。我们预计也在 12 月底发出这个 feature,性能收益也会整理出来。
这样有很多好处,可以不再受限 WebGL 2.0,也不局限使用 WebGPU。因为 WebGPU 本身走向成熟需要一定时间,而 Metal 当前就是成熟的。另外在使用 WebGPU 的情况下,手机底层驱动还是 Metal,需要一个 WebGPU 到 Metal 的转换过程,它不是 Free 的。我们跟微信探讨直接在 Performance+ 这样的方案上支持 Metal,通过这种方式,未来大家就可以在小游戏上使用上
从超休闲到MMO、策略游戏等中重度游戏,小游戏的品类越来越丰富,用户体验不断提升。Unity 中国不断加大对小游戏的支持,推出的产品“团结引擎”在小游戏开发的轻量化、多平台适配、稳定性提升等方面做了大量优化。2024 年 12 月 6 日 Unity Open Day 技术开放日厦门站将聚焦小游戏及开源鸿蒙平台的技术实现及市场探索,探讨如何利用团结引擎的最新技术,为小游戏赛道、移动端游戏注入强劲增长动力。还有闭门 Round Table ,直接对话引擎研发!亮点多多,点击!