0%

使用 Unity 2020 版本导出 Android Studio

公司有的项目是用的 Unity 2020,之前一直用的是 2018 版导出 Android Studio,切换到 2020 后发现与之前的版本改动较大,于是踩到了不少的坑。

环境版本

  • NDK 版本:Unity 2018 用的是 r18b 版本,Unity 2020 用的是 r19 版本。
  • Gradle 版本:Unity 2018 最低版本是 5.1.1,Unity 2020 最低版本是 5.6.4。

导出工程报错,提示 build cannot be appended 或者 the build target does not support build appending

原因是 Unity 从 2019.4.14f1 版本开始修改了 Android Studio 导出的选项,如果使用 Gradle 来编译,首先需要设置 EditorUserBuildSettings.exportAsGoogleAndroidProject = true ,才能导出 Android Studio。其次将 BuildPlayerOptions 中移除 BuildOptions.AcceptExternalModificationsToPlayer 这个选项。

例如:

1
2
3
4
5
6
EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle; // 使用 Gradle
EditorUserBuildSettings.exportAsGoogleAndroidProject = true; // 导出Android Studio工程

BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.options = BuildOptions.None | BuildOptions.Development; // BuildOptions.AcceptExternalModificationsToPlayer; // 导出选项
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);

导出报错,提示 `mainTemplate.gradle file is using the old aaptOptions noCompress property definition which does not include types defined by unityStreamingAssets constant.

gradle 的 noCompress 中没有定义 unityStreamingAssets 里的文件后缀名。

Uniy 2018 中的 noCompress 是:

1
2
3
aaptOptions {
noCompress = ['.unity3d', '.ress', '.resource', '.obb']
}

Unity 2020 中改成了:

1
2
3
4
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}

包含了 unityStreamingAssets 中的文件,`unityStreamingAssets 的定义在gradle.properties` 文件中:

1
2
3
4
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
unityStreamingAssets=.unity3d, test.txt

生成工程的路径变化

在 Unity 2018 中,假设设置工程路径为 ../ProjectPath,生成出来的工程路径为 ../ProjectPath/ProjectName,其中 ProjectName 是项目的名称。例如:

1
2
3
4
5
PlayerSettings.productName = "MyProject"; // 项目名称
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.locationPathName = "../Path"; // 导出的工程路径
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions); // 导出
// 最后生成的路径为 ../Path/MyProject/

在 Unity 2020 中,假设设置工程路径为 ../ProjectPath,生成出来的工程路径为 ../ProjectPath,不会再带有项目名称了。例如:

1
2
3
4
5
PlayerSettings.productName = "MyProject"; // 项目名称
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.locationPathName = "../Path"; // 导出的工程路径
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions); // 导出
// 最后生成的路径为 ../Path/

生成的Android Studio 工程结构变化

Unity 2018 生成完的工程结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- build.gradle                             // Assets/Plugins/Android/mainTemplate.gradle
- gradle/
- gradle.properties
- gradlew
- libs/ // Assets/Plugins/Android/libs 目录下的 *.jar 和 *.aar 文件
- local.properties
- proguard-unity.txt
- setting.gradle // Assets/Plugins/Android/settingsTemplate.gradle
- src/
- main/
- AndroidManifest.xml // Assets/Plugins/Android/AndroidManifest.xml
- assets/ // Unity 生成的资源,Assets/Plugins/Android/assets,Assets/StreamingAssets 目录下的文件
- java/ // java 源码
- jniLibs/ // Assets/Plugins/Android/libs/armeabi/*.so 各个架构下的 so 文件
- res/ // Unity 生成,图标,游戏名,主题等
- unity-android-resources/
- AndroidManifest.xml
- build.gradle // Assets/Plugins/Android/libTemplate.gradle
- project.properties
- res/ // Assets/Plugins/Android/res 目录下的文件

Unity 2020 生成完的工程结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- build.gradle                             // Assets/Plugins/Android/baseProjectTemplate.gradle
- gradle/
- gradle.properties // Assets/Plugins/Android/gradleTemplate.properties
- gradlew
- launcher/
- build.gradle // Assets/Plugins/Android/launcherTemplate.gradle
- src/
- main/
- AndroidManifest.xml // Assets/Plugins/Android/LauncherManifest.xml
- res/ // Unity 生成,图标,游戏名,主题等
- local.properties
- setting.gradle // Assets/Plugins/Android/settingsTemplate.gradle
- unityLibrary/
- build.gradle // Assets/Plugins/Android/mainTemplate.gradle
- libs/ // Assets/Plugins/Android/libs 目录下的 *.jar 和 *.aar 文件
- progurad-unity.txt
- src/
- main/
- AndroidManifest.xml // Assets/Plugins/Android/AndroidManifest.xml
- assets/ // Unity 生成的资源,Assets/Plugins/Android/assets,Assets/StreamingAssets 目录下的文件
- Il2CppOutputProject/ // Unity 生成,如果使用了 il2cpp 打包
- java/ // java 源码
- jniLibs/ // Assets/Plugins/Android/libs/armeabi/*.so 各个架构下的 so 文件
- jniStaticLibs/ //
- res/ // Unity 生成
- unity-android-resources/
- AndroidManifest.xml // Unity 生成
- build.gradle // Assets/Plugins/Android/libTemplate.gradle
- project.properties
- res/ // Assets/Plugins/Android/res 目录下的文件

生成 apk 失败报错,提示 processReleaseResources

使用了 ./gradlew assembleRelease 命令后报错:

1
2
3
4
5
* What went wrong:
Execution failed for task ':launcher:processReleaseResources'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
> AAPT2 aapt2-3.6.0-6040484-osx Daemon #0: Unexpected error during link, attempting to stop daemon.
This should not happen under normal circumstances, please file an issue if it does.

原因是 StreamingAssets 底下的文件太多而导致 aapt2 报错,需要分别修改 launcher/build.gradleunityLibrary/build.gradle 文件中的 aaptOptions.noCompress 选项:

1
2
3
4
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}

将后面的 unityStreamingAssets.tokenize(', ') 删除,在 noCompress 里加入 StreamingAssets中出现的文件后缀名,例如:

1
2
3
4
aaptOptions {
noCompress = ['.ress', '.resource', '.obb', '.bundle', '.unity3d', '.txt']
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}

java 代码

UnityPlayerActivity

Unity 2018 这个类在生成的 unity-classes.jar 中有,游戏主 Activity 可以直接继承。

Unity 2020 在生成的 unity-classes.jar 中没有这个类了,需要使用 Unity 生成出来的 java 文件中找到这个类。

参考链接