关于Unity手游更新的思考
本文将深入探讨Unity手游更新相关问题。大家熟知的手游安装方式主要有两种:一种是在安装时就把程序和资源全部安装到本地;另一种是仅安装程序和少量必要资源,在启动时再下载完整的缺失资源。
传统的手游更新方法
Android
通常采用覆盖更新的方式。开发者将打包生成并带有对应平台签名的 APK 上传到平台,平台会依据 versionCode 判断版本情况并提示用户升级,用户可通过桌面应用(如应用宝)或手机管家一类的手机应用进行更新。此外,Android 系统中的应用能够拉起提示安装 APK,基本可实现内部覆盖升级。
iOS
只能通过上传到 App Store 进行审核更新,审核通过后可随时对外发布。然而,审核周期通常在一周以上。
传统更新方式的弊端
传统更新方式均需玩家重新下载整个游戏包并覆盖安装。例如,某游戏经历 5 次替包更新,每次更新玩家都需完整下载 140M 的包体,每次强制更新都会导致 10% 以上的玩家流失,从相关数据图中可明显看到玩家流失情况(出现明显凹槽)。更为严重的是,iOS 的审核机制会使版本迭代时间变得不确定,遇到严重 bug 时难以发布紧急版本。
对更新方式的思考
我们需要一种增量更新方式,在更新过程中,无论是代码还是资源发生变化,都无需下载完整包,只需制作差量包。对于 iOS 小版本的更新或修复严重 bug 的紧急版本,应能够绕过审核直接发布到外网。
理想的 Unity 手游更新方法
目标
- 构建从 Unity 的资源管理到发布成手机版本的一体化流程,实现一键发布版本。
- 版本发布时制作差量更新包,资源和代码均可更新,一般情况下版本发布可绕过苹果 iOS 审核流程。
- 一般开发人员在开发过程中无需关注资源在不同平台的差异及发布过程,但使用方式不符合更新流程时要有错误提示。
- 发布平台支持版本管理、灰度测试、不同运营平台差异化一键发布。
- 在代码无需变动的情况下支持切换多语言文字包和资源包。
限制
- Android 系统的 APK 和 iOS 系统的 APP 在安装后都不允许修改包内容,包内容在系统中是只读的,这与 PC 游戏常使用的更新本地资源的升级方式截然不同。
- iOS 系统中的代码只允许以静态编译(AOT)方式发布,在法律政策上也不允许下载并执行代码,并且封锁了内存(或者堆)的可执行权限,变相封锁了 JIT 这种编译方式。
Unity 手游更新的技术选型
代码更新
由于 iOS 系统存在诸多限制,静态语言的更新必须进行苹果审核并进行整包更新。而动态脚本语言则提供了动态更新的可能性,参考市面上经过验证的方案,可将 Lua 或 JS 以文本的方式发布到手机上,从而实现游戏逻辑的修改。
版本发布流程
技术方案采用
- 自研的资源加载管理器:要求不同平台调用的加载资源接口相同,开发者调用时无需考虑是从哪个
AssetsBundle中加载的,便于后期AssetsBundle的分布优化。 - 自研的 AssetBundle 设置工具:设置过程自动化,减少人工参与,可进行多语言资源包管理,能查找重复的资源引用,方便后期优化。
- Lua 脚本语言:使用 Lua 脚本语言进行游戏逻辑开发,并发布为文本文件。
- IFS:在 release 阶段使用 IFS 进行资源打包和制作版本差异包。
- IIPS:使用 IIPS 进行手机端资源和版本更新,操作可读写的
persistent目录(iOS:Application/[packagename]/Documents;Android:/data/data/[packagename]/files)进行资源版本管理。 - Soda:使用 Soda 管理编译机进行编译。
- MTCLS 和 TVersion:使用 MTCLS 和 TVersion 管理游戏版本和资源版本的对外发布、版本号控制、灰度测试。
以上所有打包和发布流程使用脚本串联,减少人工干预。
自动化与便利性
传统更新方式存在一些额外操作,如需要设置每个文件的 assetbundle 属性;开发过程中每次修改资源都要更新 assetbundle 文件才能使用;不同端(Editor、手机端)调用加载资源方式不同。而上述加载方案实现了不同端调用相同接口加载资源,资源更改时无需更新 assetbundle 文件,同时 assetbundle 属性可自动设置。
现有方案的弊端
- 由于使用 IFS 进行
assetbundle文件的打包与版本差量包制作,第一次游戏启动时需要解压资源全量包,导致第一次启动游戏时间变长。 - 需要将游戏
assetbundle文件解压到可读写的persistent目录,造成手机空间的浪费(游戏目录下一份资源,persistent目录一份资源)。 - 可能出现
assetbundle交叉引用资源的问题。
进一步思考
- 解决首次启动时间长和空间占用问题:可采用资源加载重定向的方式,大版本将游戏资源包含在发布包中,小版本则解压到
persistent目录,再进行资源重定向,每次大版本更新后清空persistent目录。 - 解决交叉引用资源问题:可通过工具找出交叉引用的资源,再人工排除。
- 后期优化手段:在后期优化中,可采用后台在 Wi-Fi 环境下预下载更新包等方式。由于游戏中所有资源都已分出资源包,采用首次进入下载资源包、分批下载资源包等方式也便于切换。