Unity Android APP il2cpp热更新解决方案

这是Unity Android APP il2cpp热更解决方案的说明,Demo地址可点击文末阅读原文获取。

01、简介

和现有的热更解决方案不同的是,它不会引入多余的语言(只是UnityScript,c#…),对Unity程序设计和编码没有任何限制。你可以在预置和场景里的GameObject上添加任何的Compnents组件,需要序列化的和不需要序列化的,他们都是可以热更的,也不需要做额外的标记处理。简而言之,在此方案下,Unity的所有资源和脚本,都是可以热更的。

本文接下来将介绍如何去制作热更文件和如何应用这些热更文件。为了简化Demo的设计,Demo包含的热更文件会事先以全量更新的方式制作好,一起打到了Apk里面。具体到项目中热更文件得放服务器,正式上线得放CDN,以增量更新的方式捣鼓出和文中一样的目录结构就OK了。

02、方案总览

Unity在以il2cpp方式导出Android工程(或者Apk文件)的时候,代码会被编译成libil2cpp,而相关的资源、配置和序列化数据会以他们各自的格式导出到android的assets目录(assets/bin/Data)。这两部分,libil2cpp和assets目录,必须匹配(即需要在同一次打包中提取,可能有的变了,有的没变,增量方式只提取变化的部分)才能正常工作,不然Unity会在启动时崩溃。本方案就是热更这两部分。

热更的正式流程如下图:


流程说明:

步骤1,在Unity的逻辑之前,libbootstrap会检查本地是否有Patch. Apk安装后,没应用过任何热更,本地是不会有Patch文件的,走no流程。如果热更过,则会有Patch目录,走yes流程。Patch目录如何准备,后面会讲到。

步骤2,加载Patch目录对应架构(arm/x86)的libil2cpp库,并应用assets目录的更新文件。

步骤3,开始Unity的流程,进入Unity第一个场景,并执行相关的Unity Script,一般是C#,我们都以C#举例。

步骤4,检查服务端是否有新的patch,这步demo没有演示,需要自己实现。

步骤5,下载新的patch,这步demo也没有演示,需要自己实现。

步骤6,根据规则准备patch目录,详细规则会在后面描述。在Demo中只是将全量更新包解压,全量更新包打包的时候目录结构就是对的,所以不需要做其他的处理。

步骤7,调用libbootstrap的接口设置patch目录,因为libil2cpp已经加载进进程,所以需要重启APP,从新的patch目录加载patch。这步Demo中有设置patch目录的例子。

步骤8,重启APP,Demo提供了纯C#代码。

步骤9,没有新的Patch,就正常进入游戏了。

流程里更详细的描述和如何生成Patch文件,见第三章。

03、Demo详述

3.1. Demo目录结构

工程所有文件均置于AndroidIl2cppPatchDemo目录下。各文件目录说明如下表。


所有文件就这么多,项目用git管理,master分支为母包分支,version1和version2分支为热更1和热更2分支,分支间会有些细微的差别,version1主要测试序列化数据,version2添加了新场景和新脚本,具体可以diff查看。下面会详细描述打包过程和如何应用热更文件。

3.2. 打包过程

所有的打包逻辑在文件Editor\AndroidBuilder.cs里。展开主菜单AndroidBuilder, 可以看到有5步,为了和热更启动流程区分,我们就叫他过程。

过程1:以il2cpp的方式,导出Gradle Android工程。选择Gradle Android工程,而不是ADT Android工程,只是因为Unity2018不再支持ADT方式。Demo并不依赖AndroidStudio,只是导出的Android工程目录结构是以Gradle的方式注释,之后的构建步骤都是调用原始JDK/SDK的方式。Demo这部分的代码可以复用,但需要根据项目需求做一些修改。

过程2:需要修改一下Android工程,因为libbootstrap需要在进入Unity的帧循环前,检查加载本地准备好的patch。大多数情况,你可以复用这个步骤的代码。但是如果你的项目修改了Unity Java的继承体系,你需要检查一下这块代码是否有调用到。如果没有调用到,后面Unity帧循环中的逻辑和资源,用的都是Apk内的相应文件。

过程3:生成热更文件。如在第二章所述,patch分为两部分,il2cpp库和assets/bin/Data目录。具体做法代码均有提供,需要注意的是必须遵守各个文件的命名方式和相对路径。各个文件均有压缩,对于增量包,如果压缩前的文件和之前相比没有变化,则不需要制作对应的压缩文件。这部分制作压缩部分的代码可复用,增量部分需要自己实现,热更文件最好也加进版本管理(svn/git/…)中。

过程4: 生成打包的windows脚本。脚本仅依赖JDK/SDK命令,可复用。生成脚本后,Android工程就不依赖Unity了,可以随意替换文件,再次调用脚本生成新的Apk。需要注意的是,打包用的so动态库,是pkg_raw目录下的so文件,替换时请注意。首次会在Unity目录下生成keystore目录和相应的签名文件,可以将此签名替换,并修改导出脚本中的签名密码。

过程5: 执行过程4中的脚本,生成Apk安装文件,可复用。

主菜单AndroidBuilder下还提供了菜单“Running Step 1, 2, 4, 5 for the base version”,这是一键构建母包版本用的,母包不需要制作patch文件,所以少了过程3;和菜单“Runnnig Step 1-4 for patch versions”,这是一键构建Patch用的,因为在demo里,不需要导出Apk文件。

关于打包这里得多说两句。 如果没有采用AssetBundle的方式打包,Unity会按各自格式,将所有场景和依赖输出到assets/bin/Data目录,这样子也是可以热更的。但是,不要这么做,因为这样做微小的改动会影响到多个文件,导致热更文件过大。最好是自己用AssetBundle的方式将资源做一个清晰的划分,打包好的AssetBundle放在assets下的其他目录。需要注意和libil2cpp库和assets/bin/Data的文件向匹配(保证是同一个版本的输出)。运行时可以重写AssetBundleManager.overrideBaseDownloadingURL加载最新的AssetBundle。

3.3. 运行时应用热更文件

我们回顾一下第二章的流程图,结合打包过程和Demo的代码,做进一步的说明。


打包过程2里,在Unity的游戏逻辑之前,插入了三行Java代码。


这三行代码保证了上图中步骤1-2能在步骤3之前执行,下一行mUnityPlayer的代码即开始了步骤3的执行。步骤3之后所有的逻辑,都是已热更过的il2cpp库里的Unity Script(c#,…)了。热更部分的逻辑如果有修改,会在热更后体现,如果这部分的bug不影响下次热更,则可以通过热更修复,否则应指引用户清除本地数据,以母包热更逻辑更新到最新。所以,在方案的应用中,仍需尽量保证热更部分的代码稳定,不能随意更改。

如前所述,Demo里没有步骤4和步骤5的相关逻辑,步骤6中Patch的准备,Demo只是简单地将全量压缩包解压,相关逻辑在Script/VersionSettor.cs文件中。准备更新目录时,应保证libil2cpp部分被解压,命名方式和Demo保持一致,而assets_bin_Data下的文件不需要解压,应保证目录结构和Demo保持一致。如果是增量更新,Patch目录下的文件应该是相对于母包的修改文件。在持续热更中,应保证在步骤7前,本地当前Patch目录的完整性(保证运行中的App还能正常执行),新的Patch应新建目录,通过硬链接的形式从当前Patch目录中提取所需要的没变化的文件,准备好后执行步骤7,重启后将老Patch目录删除. 步骤7和步骤8的代码也在Script/VersionSettor.cs文件中,样子如下:


04、Verity和Build

4.1. Verify

安装预编译的Apk文件,点击按钮可以切换各个版本(点击文末阅读原文,可获取Apk链接)。

4.2. Build

依赖

  • Unity (我用Unity2017/Unity2018)
  • JDK.(我用JDK1.8)
  • Android SDK.(我用Android SDK platform 23 和 build tools 26.0.2(低于26.0.2,Unity2018不支持),最好是这两个版本,不然得重新下载)
  • Android NDK r13b. (Unity il2cpp原来只支持这个版本,现在不知道放开没,反正这个版本没问题)
  • Git


Build指引

  • 在Unity中(Edit->Preference->External tools)设置好 JDK/SDK/NDK 路径,打包代码里会从Unity中读取。
  • 如果你的Android SDK的build tools版本不是26.0.2,需要修改代码AndroidBuilder.cs,第14行。
  • 如果你使用的Android platform不是android-23,修改代码 AndroidBuilder.cs,第15行。
  • 出母包,执行菜单 AndroidBuilder->Run Step 1, 2, 4, 5 for base version, 成功后会弹出文件管理器显示apk所在的目录.
  • 一般来说你不需要打Patch文件,如果要打,用git checkout version1或version2,执行菜单 AndroidBuilder->Run Step 1-4 for Patch Version。PrebuildPatches目录下的相应文件会被更新。


05、剩下的工作和建议

打包部分

  • 设置部分需要根据项目实际做修改。
  • 热更文件的增量版本化管理。


运行时部分

  • 检查新版本和下载热更文件。
  • 持续增量更新的Patch目录的准备。


用Asset Bundle管理资源。

另外,打包的工作尽量自动的一键化,一次化,除非你想在打包当晚集体晒月亮。另外,低成本的打包流程,大家都愿意在真机上看结果,利于产品的稳定。Demo其实提供了一套自动化的框架和脚本,理解透,化为己用,也是幸事一件。如果有更好的方式,欢迎讨论。

来源:腾讯游戏学院
原地址:http://gad.qq.com/article/detail/288713


你的产品有必要投广告么?亚马逊站内广告策略常见问题解答

对于亚马逊站内广告,投放与否,其所带来的订单结果几乎是立竿见影的,一条表现不太差的Listing。只要投放了站内广告,其订单数量必然会有所增长。

Unity 内存管理和profiler详解

Unity Memory Management Unity 的 Memory 构造 实际上Unity游戏使用的内存一共有三种:程序代码、托管堆(Managed Heap)以及本机堆(Native Heap)。 程序代码包括了所有的Unity引擎,使用的库,以及你所写的所有的游戏代码。在编译后,得到的运行文件将会被加载到设备中执行,并占用一定内存。 这部分内存实际上是没有办法去“管理”的,它们...

Unity在Android设备中的icon适配

应用icon图标适配 前言: 游戏上了 Google Play 之后,若没有做 Android 8.0 及更高版本的 icon 适配. 就会出现以下3个不适配的图标样式. 谷歌从 Android 8.0 后就设计了一套将 icon 分为前景和背景的方式拼接,这样还可以实现很好的 icon 效果。 详细科普请见以下链接: Understanding Android Adaptive Icons...

unity圆圈自动吸附屏幕边缘

效果: 设置如下:

Unity 导出 iOS 游戏并上架 App Store

logread/1878Unity 导出 iOS 游戏并上架 App Store 0. 前言 因为之前已经上架过一款 App(Swift 语言),所以开发者账号、证书这些都已经搞定了,如果你是第一次上架 iOS 应用,具体流程可以参考本文末尾列出的教程。这