介绍

本文介绍 Unity 如何打包 Android 应用,生成可运行的 apk 文件。

系列

环境

  • Unity 2019.4.32f1
  • Android Studio 2021.1.1
  • Windows 10 21H2

项目中使用的软件版本非常重要,直接决定了各种依赖的版本。一定要正确并完整地记录软件版本,很多时候只是一个小版本的差异就会有很大区别,例如 Unity 2019.4.0f1 与 Unity 2019.4.32f1 发布时间隔了 16 个月,那么支持的 Android SDK、Xcode 版本等都会有较大差异。

准备

上面的环境中并没有列出 Android SDK、Android NDK、JDK 的版本,是因为 Unity 现在使用 Unity Hub 安装管理这些依赖,并且已经正确地设置好了正确的依赖版本,也就是说实际使用时不用费心地测试兼容当前版本 Unity 的依赖版本。

如果之前是手动下载 Unity 安装文件安装的,建议这里改为使用 Unity Hub 安装。之前尝试搜索过把已安装版本纳入 Unity Hub 管理,但实际上 Unity Hub 完全不支持这种方法。好在如果网络较好的情况下,Unity Hub 安装一个新版本速度非常快,而且 Unity 中国已经增加了中国的 CDN,实际速度还不错。

安装完 Unity 后建议逐个安装 Android Build SupportAndroid SDK & NDK ToolsOpenJDK,防止由于网络原因导致某一个下载失败后导致整体安装失败。

手动打包

可以新建一个空白 Unity 工程进行手动打包测试,这样可以极大地节省项目导入或转换平台的时间,因为测试时需要的是高效率迭代。推荐新建的测试工程以 Test 开头并描述大概内容,例如:TestUnity2019.4.32f1BuildAndroid

Unity 打包 Android 时弹窗提示安装的 SDK Build Tools 版本过低:

1
2
3
4
5
6
7
Detected outdated SDK Build Tools version 28.0.3 when the min version is 29.0.2
UnityException: SDK Build Tools version 28.0.3 < 29.0.2.
Note: when building with Gradle, "Use Highest Installed" option will update SDK Build Tools as well.

Update Android SDK
Use Highest Installed
Cancel

选择 Use Highest Installed,下次打包时依然会弹此对话框。选择 Update Android SDK 会提示权限不足,无法创建目录:

1
2
3
UnauthorizedAccessException: Access to the path "C:/Program Files/Unity/Hub/Editor/2019.4.32f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\tempToolsDir" is denied.
  at System.IO.Directory.CreateDirectoriesInternal (System.String path) [0x0005e] in <eae584ce26bc40229c1b1aa476bfa589>:0 
  at System.IO.Directory.CreateDirectory (System.String path) [0x0008f] in <eae584ce26bc40229c1b1aa476bfa589>:0 

使用管理员运行 Unity Hub,并打开工程,这时 Unity 就会继承管理员权限,再次安装提示:

1
2
3
PathTooLongException: Path is too long. Path: C:/Program Files/Unity/Hub/Editor/2019.4.32f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\tempToolsDir\lib\monitor-x86\p2\org.eclipse.equinox.p2.engine\profileRegistry\DefaultProfile.profile\.data\org.eclipse.equinox.internal.p2.touchpoint.eclipse.actions
System.IO.Directory.CreateDirectoriesInternal (System.String path) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.IO.Directory.CreateDirectory (System.String path) (at <eae584ce26bc40229c1b1aa476bfa589>:0)

怀疑系统没有开启长路径支持,但记得安装 Python 3.10 时已经在最后开启了此选项。运行 regedit 查看注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem 确认其中的 LongPathsEnabled 值为 1,之前重启过系统,说明长路径已经生效了。

这个问题 Unity 问答网站上有人遇到了,给出的方案是重新安装 Unity 到 C:\Unity 目录中,但是这没有解决根本问题。

由于 Unity 自带 Android SDK 的安装目录在 C:\Program Files\ 中,需要管理员权限才可以修改。实测使用管理员权限运行 Android Studio 并用其中的 SDK Manager 来更新 Unity 内置 Android SDK,虽然提示下载成功,但是却无法成功更新。

可以从 Android Studio 安装的 Android SDK 目录里拿到新版本 SDK Build Tools,拷贝 %LOCALAPPDATA%\Android\Sdk\build-tools\32.0.0C:\Program Files\Unity\Hub\Editor\2019.4.32f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\ 目录中,然后重启 Unity 生效。

自动打包

Unity 打包 Android 需要使用 C# 编辑器脚本,这里可以参考 Unity 官方文档:

核心就是一个 API BuildPipeline.BuildPlayer,手动打包就是点击按钮后调用这个方法,自动打包就是直接调用这个方法。

注意:Unity 内部使用缓存保存当前项目 Assets 目录的整个目录结构,如果在 BuildPipeline.BuildPlayer 执行前对目录结构进行了改动,那么打包时就会报错。例如 Assets/Plugins/Android/libs 目录下的文件出现删除或改名,打包时就会提示删除或改名前的文件不存在。所以正确的处理方法是在调用 BuildPipeline.BuildPlayer 前执行 AssetDatabase.Refresh() 强制刷新缓存一次。

完成后使用命令行进行打包,具体参考 Unity 官方文档:

注意:Unity 2019.4.32f1 实测使用 -nographics 参数会导致打出 Android 包进入场景后变粉,检查对比发现 assets/bin/Data/Resources/unity_builtin_extra 中的 Shader 都是空的,去除 -nographics 参数后打出来的包 Shader 都是正常的。

测试

打包出来的 apk 推荐使用模拟器进行测试,这样可以不用等待拷贝文件到手机,再手动操作安装运行了,极大提升效率。

推荐使用夜神模拟器,官网支持 Android 9 版本,相对其他模拟器来说更新一些。

总结

第一步最重要的是打出一个可运行的包,这意味着环境、依赖都已经准备好。在这个过程中,可以记录下软件的版本、依赖是如何安装的、安装先后顺序等等,整理成为一个文档方便后续他人使用。