尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Unity打包APK实战:从环境配置到命令行自动化

Unity打包APK实战:从环境配置到命令行自动化 做 Unity 开发的朋友应该都有过这样的经历在编辑器里运行得好好的 Demo想拿到真机上跑一下结果被 APK 打包卡住了。要么是点击 Build 之后报一堆 SDK / JDK 错误要么是打包流程走到一半就失败要么是好不容易打出来的 APK 安装不到手机上。网上关于 Unity 打包 APK 的资料很零散很多帖子只讲了“点一下 Build”没有说环境怎么配、Player Settings 为什么要这样设置、脚本打包怎么自动化。本文把这些内容整合成一套完整的实战笔记从环境准备、Unity 面板配置、GUI 打包、USB 安装到命令行自动化打包都会讲到并附上常见报错排查表。新手朋友可以照着一步步操作已经在项目里的开发者也可以直接跳到自己需要的章节。注意一点本文只讲 Android 原生 APK 的打包链路。如果你想做的是 HarmonyOS、微信小游戏、抖音小游戏那是另一套配置流程不在下面的讨论范围内。1. Unity 打包 APK 的底层逻辑1.1 为什么打包 APK 不是“点一下 Build”这么简单Unity 编辑器本身只是一个开发工具它不会帮你完成 Android 编译。点击 Build 后Unity 会调用本地的 Android SDK、NDK、JDK 来一起完成把 C# 代码编译成 IL再根据打包设置转成 Mono 或 IL2CPP 可执行文件把场景、材质、贴图、音频、预制体、Shader 等资源按规则序列化并压缩生成 Android 工程文件再用 Gradle 编译资源、生成 Dex、打包资源最后用 jarsigner / apksigner 完成签名生成可安装的 APK。所以打包 APK 的本质是一个“Unity Android 工具链联动”的过程。哪个环节缺失最终都会在 Build 窗口里反馈出来。1.2 快速打包的核心是什么“快速”并不是指让 Unity 把构建时间从 10 分钟压缩到 1 分钟而是指“通过规范化的环境配置和重复步骤自动化减少中途踩坑和反复检查的时间”。构建速度很大程度上取决于是否开启增量构建使用 Mono 还是 IL2CPP场景和资源是否精简是否配置了 SDK / NDK 的缓存路径是否在命令行中跳过不必要的导入和初始化。这篇文章不会教你“黑科技加速”而是把影响打包成功率的环节都梳理清楚让你在第一次构建时就能一次通过后续再通过脚本一键完成整体效率自然就上去了。1.3 适合什么类型的项目本文的内容适用于Unity 2020 LTS、2021 LTS、2022 LTS 及更新版本纯 Android 原生 APK 打包真机安装测试需要接入 SDK 或自动化打包的团队项目。如果你的项目已经使用了 Jenkins、GitLab CI 等自动化平台本文的 BuildScript.cs 也可以直接作为构建入口。2. 打包前环境准备在打开 Build Settings 之前先确保本机环境基本满足条件。很多人一上来就点 Build结果报错信息全是英文最后发现是 JDK 没装这种情况很常见。2.1 需要准备哪些组件组件作用是否必装Unity 编辑器项目开发和打包入口必装Android Build Support 模块Unity 导出/编译 Android 工程的能力必装Android SDK提供 adb、aapt、zipalign 等工具必装Android NDKIL2CPP 交叉编译时使用使用 IL2CPP 时必装OpenJDK编译 Java/Kotlin、生成签名必装USB 驱动连接 Android 手机时使用使用真机调试时推荐这里最重要的不是“自己单独去官网下载”而是通过 Unity Hub 安装 Android Build Support。如果你安装了多个 Unity 版本尽量让每个版本的 Android Build Support 模块保持完整。2.2 使用 Unity Hub 安装模块打开 Unity Hub进入“安装”标签页。找到当前项目使用的 Unity 版本点击右侧齿轮图标选择“添加模块”。在模块列表中勾选Android Build SupportAndroid SDK NDK ToolsOpenJDK。勾选后点击“安装”Unity Hub 会自动把 SDK、NDK、OpenJDK 下载到你本机的默认目录。这是比较省心的方式也是新手朋友最推荐的方式。2.3 检查本机环境是否就绪安装完成后打开 Unity 项目进入菜单Edit - Preferences - External Tools在 Android 一栏中可以看到SDK 路径NDK 路径JDK 路径。如果你是通过 Unity Hub 安装的模块这三个路径通常会自动填入。如果路径是空的或者带黄色警告图标需要手动指定。SDK 最终路径一般是C:\Program Files\Unity\Hub\Editor\版本号\Editor\Data\PlaybackEngines\AndroidPlayer\SDKJDK 路径类似C:\Program Files\Unity\Hub\Editor\版本号\Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK不同版本和系统盘的安装路径可能不同以你本机实际路径为准。如果你是手动下载的 SDK需要注意 SDK 平台和 Build-Tools 的版本是否被 Unity 支持。遇到版本不匹配时优先考虑用 Unity Hub 重新安装模块而不是自己去下载一堆 SDK Tools。3. Unity Android 打包关键配置拆解3.1 进入 Player Settings打开菜单File - Build Settings点击左下角的“Android”再点击“Player Settings…”右侧的 Inspector 会变成 Android 相关的设置面板。这些设置项很多但真正影响首次打包成功率和安装成功率的主要是下面几类。3.2 包名、版本号与应用标识在 Other Settings 中Package NameAndroid 应用唯一标识一般使用反向域名例如com.example.myunitygameVersion给玩家看到的版本号例如1.0.0Bundle Version Code内部版本号必须是整数每次上传商店前需要递增例如1、2、3。Package Name 不要随便起。如果你之前已经安装过相同包名的应用新安装包签名一致才能覆盖安装。建议从项目开始时就想好固定包名后续不要再改。3.3 脚本后端Mono 还是 IL2CPP在 Other Settings 中找到 Scripting Backend可选值Mono编译快打包体积略大兼容性也好IL2CPP构建慢但运行时性能更好APK 体积更小并且更适合商用项目提交商店。对于“快速打包到手机”的需求第一次测试建议先用 Mono。等到正式发布或需要接入微信、抖音等平台时再切到 IL2CPP。切换 IL2CPP 后Unity 会使用 NDK 进行 C 编译首次构建时间会比 Mono 长很多这是正常的。3.4 纹理压缩格式在 Other Settings 中找到 Texture Compression常见选项Dont override使用贴图原始格式ASTC兼容 Android 6.0 以上主流设备ETC2兼容性较好但部分老设备不支持。在新项目中建议选择 ASTC这是当前 Android 设备的默认趋势。如果你的项目要兼容很老的机型再根据测试结果调整。3.5 横竖屏和应用图标在 Resolution and Presentation 中Default Orientation 选择 Portrait、LandscapeLeft / LandscapeRight 等手机应用的图标在 Icon 面板中设置不设置的话会使用 Unity 默认图标。在真机测试前建议把 Target Minimum API Level 设置为与你手机 Android 版本接近或更低的值。如果设置过高低版本手机会无法安装。3.6 Android 签名配置Android 要求所有 APK 必须签名后才能安装。在 Player Settings - Publishing Settings 中勾选 Create a new keystore可以生成一个本地密钥库也可以直接勾选 Use existing keystore导入已有的 keystore。对于个人开发测试可以勾选 “Custom Keystore”然后在 Unity 里创建新密钥库。Unity 会自动填写 keystore 中的 alias、password 等信息。如果你不想在编辑器中操作也可以使用 JDK 自带的 keytool 命令生成keytool -genkeypair -v -keystore release.keystore -alias mygame -keyalg RSA -keysize 2048 -validity 10000执行过程中会要求输入密码、姓名、组织等信息。生成后的release.keystore文件要妥善保存不要提交到公开仓库。以后每次打包这个文件必须保留否则用户无法覆盖安装旧版本。4. 手把手Unity 快速打包 APK 到手机接下来是一个完整的 GUI 打包流程。假设你的项目已经能在 Unity 编辑器里运行场景也已经保存。4.1 把场景添加到 Build Settings打开File - Build Settings点击“Add Open Scenes”把当前打开的场景加到列表。请检查场景是否已经勾选启动场景是否为列表中的第一个场景如果后续要打包多个场景确保跳转关系正确。很多人第一次打包出来的 APK 打开后黑屏就是因为场景列表为空或者没有把场景添加进去。4.2 选择 Android 平台在 Build Settings 左侧平台列表中点击“Android”然后点击右下角“Switch Platform”。切换到 Android 平台后Unity 会重新导入部分资源耗时取决于项目大小。此时左上角会出现一个转圈进度条耐心等它完成。切换完成后Build 按钮变成可点击状态。4.3 设置公司名和产品名打开菜单Edit - Project Settings - Player在 Company Name 和 Product Name 中填写你的项目信息。Product Name 会显示在手机桌面上的应用名称Company Name 会参与默认命名空间和包名的生成。4.4 执行 Build回到 Build Settings 窗口点击“Build”按钮选择一个输出目录输入 APK 文件名例如MyGame.apk。Unity 会开始执行打包底部状态栏会显示构建进度。第一次构建通常需要较长的时间因为要生成 Android 工程、编译资源、做代码转换。4.5 将 APK 安装到手机打包成功后会生成一个 APK 文件。接下来用 USB 连接手机在手机上打开“开发者选项”开启“USB 调试”和“USB 安装”。然后将 APK 传到手机或者使用 adb 命令安装。先确认 adb 路径。如果你通过 Unity Hub 安装了 SDKadb 一般在C:\Program Files\Unity\Hub\Editor\版本号\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\adb.exe在命令行中执行adb devices手机首次连接时屏幕会弹出“允许 USB 调试”的提示点击允许。确认设备列表中出现你的设备后再执行安装adb install -r MyGame.apk-r表示如果已经安装过相同包名则覆盖安装。安装成功后在手机桌面找到应用图标点击即可运行。5. 使用命令行与编辑器脚本实现一键打包每次打开 Unity 编辑器然后手动点 Build对于个人项目还能接受。到了项目后期频繁出包时这套流程非常浪费时间。更推荐的做法是写一个编辑器脚本把打包逻辑固化下来再通过命令行一键执行。5.1 为什么要用脚本打包脚本打包的好处不需要打开完整编辑器界面适合在服务器或者 CI 环境执行可以保证团队中每个人都使用同一套打包参数可以自动切换平台、自动生成版本号、自动输出到固定目录可以配合 Jenkins、GitLab CI 做每日构建。下面给出一个最简可用版本可以作为你项目里的打包入口。5.2 创建 BuildScript.cs在项目的Assets/Editor目录下创建文件BuildScript.cs。如果Assets下没有Editor文件夹可以右键新建。// 文件路径Assets/Editor/BuildScript.cs using System.Collections.Generic; using UnityEditor; using UnityEditor.Build.Reporting; using UnityEngine; public static class BuildScript { public static void BuildAndroid() { // 切换到 Android 平台 EditorUserBuildSettings.SwitchActiveBuildTarget( BuildTargetGroup.Android, BuildTarget.Android ); // 组装构建选项 BuildPlayerOptions buildPlayerOptions new BuildPlayerOptions(); buildPlayerOptions.scenes GetEnabledScenes(); buildPlayerOptions.locationPathName GetOutputPath(); buildPlayerOptions.target BuildTarget.Android; buildPlayerOptions.options BuildOptions.None; // 执行构建 BuildReport report BuildPipeline.BuildPlayer(buildPlayerOptions); BuildSummary summary report.summary; if (summary.result BuildResult.Succeeded) { Debug.Log(Build Succeeded! Output: summary.outputPath); Debug.Log(Build Size: summary.totalSize bytes); } else if (summary.result BuildResult.Failed) { Debug.LogError(Build Failed!); // 命令行模式下失败时退出并返回非 0 错误码 EditorApplication.Exit(1); } } private static string[] GetEnabledScenes() { Liststring scenePaths new Liststring(); foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes) { if (scene null || !scene.enabled) { continue; } scenePaths.Add(scene.path); } return scenePaths.ToArray(); } private static string GetOutputPath() { string outputDirectory Build/Android; if (!System.IO.Directory.Exists(outputDirectory)) { System.IO.Directory.CreateDirectory(outputDirectory); } string apkName Application.productName.Replace( , _) _ PlayerSettings.bundleVersion .apk; return System.IO.Path.Combine(outputDirectory, apkName); } }这段脚本做了三件事使用SwitchActiveBuildTarget切换到 Android 平台读取EditorBuildSettings.scenes中启用状态的场景作为打包场景列表调用BuildPipeline.BuildPlayer构建 APK输出到Build/Android目录。脚本中的GetEnabledScenes和GetOutputPath都是可复用的辅助方法。以后想改输出目录、改 APK 文件名只需要改这两个方法。5.3 用命令行调用打包保存脚本后不需要打开 Unity 编辑器。打开命令行工具Windows 下打开 CMD 或 PowerShell执行以下命令C:\Program Files\Unity\Hub\Editor\2021.3.16f1\Editor\Unity.exe -batchmode -quit \ -projectPath D:\MyUnityProject \ -executeMethod BuildScript.BuildAndroid \ -logFile build_android.log注意这里2021.3.16f1只是示例版本号请替换为你本机实际安装的 Unity 版本projectPath指向你的 Unity 项目根目录executeMethod必须写完整包括类名和方法名-quit表示构建结束后自动退出 Unity-batchmode表示在无窗口模式下运行-logFile可以把日志输出到文件中方便排查问题。执行过程中命令行窗口会一直等待直到打包完成。如果构建成功在Build/Android目录下会生成 APK 文件。5.4 命令行打包进阶批量版本号如果需要在不同分支打不同版本可以让脚本读取环境变量或者命令行参数。例如在BuildScript.cs中增加一个BuildAndroidWithVersion方法public static void BuildAndroidWithVersion() { string version System.Environment.GetEnvironmentVariable(UNITY_BUILD_VERSION); if (!string.IsNullOrEmpty(version)) { PlayerSettings.bundleVersion version; } BuildAndroid(); }然后在命令行中设置环境变量set UNITY_BUILD_VERSION1.2.0或者使用 PowerShell$env:UNITY_BUILD_VERSION1.2.0这样可以在不修改代码的情况下动态指定版本号便于自动化发布。5.5 如何验证脚本是否生效第一次使用脚本打包后打开build_android.log文件搜索关键字Build Succeeded说明打包成功Build Failed说明失败需要往上翻日志查看具体报错如果出现Invalid executeMethod说明类型名或者方法名写错了。建议在项目里的Assets/Editor目录放一个BuildScript.cs然后在命令行模式里反复验证确认脚本稳定后再接入 CI。6. 常见问题与排查思路打包 APK 的过程会暴露各种环境问题。下面整理了一份高频问题清单适合直接对照排查。问题现象常见原因排查思路点击 Build 后提示找不到 SDKUnity 无法定位 Android SDK检查 Preferences - External Tools 中的 SDK 路径重新安装 Android Build Support提示找不到 NDK使用 IL2CPP 但没有安装 NDK在 Unity Hub 中添加 NDK 模块或手动指定 NDK 路径提示找不到 JDK没有安装 OpenJDK安装 Unity 自带的 OpenJDK或在 Preferences 中指定 JDK 路径构建到一半报 Gradle 相关错误Android Gradle 下载失败或版本不匹配检查网络尝试重新构建可通过脚本固定 Gradle 版本提示包名不合法Package Name 含中文或特殊符号改为com.xxx.xxx形式只能包含字母、数字、点、下划线安装到手机时提示“应用未安装”签名不一致、手机版本低于 minSdk、APK 损坏卸载旧应用再安装检查 minSdk重新打包安装后打开黑屏场景未添加到 Build Settings在 File - Build Settings 中添加场景并启用IL2CPP 构建非常慢首次构建需要生成 C 工程并编译后续增量构建会变快或开发阶段先用 Mono输出 APK 体积极大纹理格式未压、包含大量 Debug 日志开启资源压缩切换 IL2CPP移除无用资源6.1 最常见的 Gradle 报错很多 Unity 版本默认使用 Gradle 构建 Android 工程。在首次构建时Unity 会尝试下载 Gradle 依赖。如果网络不稳定会出现类似A problem occurred configuring root project unityProject. Could not resolve all artifacts for configuration :classpath.解决方案检查网络连接重启 Unity 并重新构建如果公司或内网有 Maven 镜像可以在Assets/Plugins/Android/mainTemplate.gradle中替换仓库地址使用 Unity Hub 固定同一版本避免版本抖动。这里不建议直接手动改 Gradle 全局缓存优先通过 Unity 的依赖配置解决。6.2 真机安装失败怎么办如果打包成功但安装失败按以下顺序排查手机是否开启了“允许安装未知来源”手机是否开启了“USB 调试”是否已经安装了相同包名但签名不一致的旧应用如有则先卸载APK 是否解析失败可以通过重新打包解决手机 Android 版本是否低于 APK 的 minSdk。建议把手机系统版本、Unity 版本、SDK 版本记下来这样在社区提问时也能更快定位问题。7. 最佳实践与工程建议7.1 尽早固化打包脚本项目刚开始时Create 几个简单场景后就应该先做一次完整的 Android 打包。不要等整个项目变复杂后再去排查环境问题。第一次接触 Unity Android 开发时先把最小场景打包、安装到手机这样后面每加一个功能都能快速验证。建议在项目初始化时就把Assets/Editor/BuildScript.cs建好并把输出目录固定到项目外或者Build/Android目录下。打包产物不要提交到 Git 仓库否则仓库体积会迅速膨胀。7.2 统一开发环境版本Unity 项目中经常出现“本地能跑CI 上失败”的问题。原因往往就是本地和 CI 的 Unity 版本、Android SDK、NDK、JDK 版本不一致。建议团队在项目根目录存放ProjectSettings/ProjectVersion.txt里面记录了 Unity 版本。运行时使用相同版本的 Unity Hub 命令行模式执行构建脚本。7.3 签名文件的安全管理keystore 文件包含证书和私钥泄露后别人可以伪造你的应用签名进行恶意版本分发。建议签名文件和密码不要提交到 Git在不同电脑上构建时从安全的密码管理工具中获取发布到应用商店的签名文件如果丢失将无法以原包名更新应用务必多重备份开发阶段和发布阶段可以使用不同签名但都要保持稳定。7.4 构建日志与版本号每次打包生成 APK 后可以通过 APK 文件名体现版本信息。例如MyGame_1.0.0.apk MyGame_1.0.0_20250410.apk MyGame_1.0.1_20250410.apk如果使用脚本构建文件名由Application.productName和PlayerSettings.bundleVersion拼接而成。这样每次出包后都能直接根据文件名判断版本。同时建议在构建脚本中输出summary.outputPath和summary.totalSize到日志方便后续追踪 APK 大小变化。7.5 开发阶段用 Mono发布阶段用 IL2CPP开发阶段快速做真机验证时优先使用 Mono构建速度快很多。等到准备提交应用商店或者性能优化时再切换到 IL2CPP。切换 IL2CPP 后建议多做一次全量构建因为首次需要生成 C 工程并编译耗时会比较久。如果项目使用了 Lua 或原生插件也需要在 IL2CPP 模式下额外测试。7.6 真机测试前做这几件事不要等到项目全部完成后再拿到真机上跑。以下几点是实践中比较值得注意的在手机上开启“保持屏幕唤醒”保持 USB 线质量稳定优先使用原装线每次打包前先清理手机里旧版本使用 adb 的logcat查看运行日志错误信息比弹窗更直接如果按钮点击无响应优先检查 UI 的 EventSystem 是否存在。例如查看 Unity 应用日志adb logcat -s Unity这条命令会过滤出 Unity 输出的日志包括Debug.Log、异常堆栈等。真机上报错时往往靠 logcat 定位。7.7 善用增量构建Unity 的增量构建可以减少重复编译时间。在日常开发中尽可能不要频繁删除Library目录不要在构建过程中强制清理所有缓存使用同一个输出目录和同一个项目目录。命令行模式下每次执行-quit会退出编辑器但Library目录中的缓存仍然保留。下次构建时 Unity 会复用这些缓存构建速度会明显加快。8. 最后的一些建议Unity 打包 APK 到手机本身并不复杂关键在于环境干净、配置规范、流程可重复。把上面提到的环境检查和打包脚本都准备好后后面每次出包只需一条命令省下来的时间可以用在实际开发和联调上。在你的第一个真机项目里可以把目标定得小一点新建一个只有一个 Cube 的场景完成从环境配置到 APK 上手的全流程。把这条流程走通以后再去研究资源压缩、IL2CPP、SDK 接入、自动化发布会顺利很多。如果本文对你有帮助可以先收藏备用后续打包时遇到问题随时对照排查。
返回列表