Unity + Play Asset Delivery | 突破Google Play 商店 150 MB 的限制
這篇文章將詳細介紹將 Play Asset Delivery 整合至 Unity 的兩種方式,以及如何測試他們
為什麼需要Play Asset Delivery (PAD)
Google宣布自 2021 年 8 月起,在 Google Play 新發布的所有應用程式都必須採用 Android App Bundle (AAB),如果大小超過 150 MB,可以使用 Play Asset Delivery 或 Play Feature Delivery。
意思是如果你的遊戲是在 2021/08 後新上架的而且大小超過 150 MB 就必須採用Play Asset Delivery將App拆包,才能上架至Play商店。至於Play Feature Delivery主要是給非遊戲類的App做使用的,這邊不討論。
PAD可以將你的App拆成base
和asset packs
,只要base
小於 150 MB、asset packs
總和小於 2 GB 就可以上傳至Play Store,然後把Play Store當成你的免費CDN Server在用。
Android App Bundle (AAB) 是什麼
傳統在Google Play上架的檔案為 APK 檔案格式,是一種能直接從手機安裝的壓縮檔。
而 AAB 為Google新推出的發布格式,與 APK 不同,他不能從手機安裝,而是必須透過上傳至Play Store後才能使用。
當玩家從Play Store下載時,Play Store會根據玩家的裝置資訊,然後從AAB生成對應的APK給玩家下載。該APK是依據裝置做過最佳化的檔案。
AAB的好處是開發者只需要上傳同一個檔案即可達成最佳化,而不需要像以往必須根據裝置分別build出不同設定的APK檔案。
例如原本使用APK的遊戲可能同時包含了ARMv7和ARM64的lib,使用AAB的話Play會根據裝置不同,讓使用者自動得到更小更優化的APK (只包含其中一個lib)
未上架的App從2021/08開始必須使用AAB;已經上架需要更新的舊App則沒有規定何時需要轉換成 AAB 發布格式,目前看起來至少會支援到2022年4月。
在Unity中引入PAD的兩種方法
目前要使用PAD主要有兩種方法,擇一使用即可:
(1). 使用Unity官方提供的功能
(2). 使用Google提供的Play Plugins for Unity
以我自己的經驗來說,使用選項(1)的體驗會比較好,包括:
→ App啟動速度較快(可能是因為Scene0的資源有被包含在base裡的關係)
→ 產生的apks檔案較小
→ 使用方法可以很簡單
以下兩種方法都會分別介紹使用方式。
(1) 使用Unity官方提供的功能
支援的Unity版本:
- 2021 → 2021.2.0b4 以上
- 2020 → 2̵0̵2̵0̵.̵3̵.̵1̵5̵f̵2̵ 2020.3.26f1 以上
- 2019 → 2̵0̵1̵9̵.̵4̵.̵2̵9̵f̵1̵ 2019.4.35f1以上
2022/02 更新:使用PAD會造成少部分Android裝置閃退的Bug,可以透過更新Unity版本解決。Nice job, Unity.
以下都是以 Unity 2019.4.29f1 做為範例
步驟1 : 升級Gradle版本至6.1.1,Gradle Plugin至4.0.1
PAD需要6.1.1以上版本的Gradle才支援,Unity2019內建的Gradle版本是5.1.1
如果是使用 2020 以上的Unity版本可以跳過這步,因為內建的 Gradle 版本已經是 6.1.1。
請至Gradle官方網站下載6.1.1的release binary後安裝。
然後取消打勾 Unity → Preference → External Tools → Gradle installed with Unity
將底下的路徑指向剛剛安裝好的gradle 6.1.1的位置
另外如果在Android的Publish Settings有勾選custom (Main/Launcher/Base) Gradle Template的話,也需要一併做以下的調整
打開 Assets/Plugins/Android 底下的.gradle檔案找到其中一行
classpath ‘com.android.tools.build:gradle:’
將後方的版本從3.4.0修改成4.0.1
此為gradle plugin版本非gradle版本,詳情可以參考這個對照表 Android Gradle Plugin
此外,launcherTemplate.gradle檔案需要做額外改動,拉到下方找到
}**PACKAGING_OPTIONS****SPLITS****BUILT_APK_LOCATION**
把它修改成
}**PACKAGING_OPTIONS****PLAY_ASSET_PACKS****SPLITS****BUILT_APK_LOCATION**
因為Unity的gradle語法有新增一項 **PLAY_ASSET_PACKS** 的關鍵字,請確保你的custom launcherTemplate.gradle 也有這個snippet,否則PAD功能會不正常 (踩到的坑之一… Orz)
步驟2 : 將Split Application Binary選項勾選
在ProjectSettings → Android → Publish Settings 最底下有個 Split Application Binary,將其勾選
原本這是會讓 APK 產生 APK Expansion Files (.oob) 的選項,但在build target選AAB的情況下會變成使用Play Asset Delivery
步驟3 : 檢查你的Asset Pack大小
在勾選Split Application Binary後,就可以開始嘗試Build你的AAB檔案了,Unity會自動將你的遊戲分包。
如果你的asset pack大小在1 GB以內,恭喜你,你已經完成了。可以跳到下方的 [如何測試用Play Asset Delivery建置出的AAB檔案]。檢查asset pack大小的方式也在裡面。
如果你的專案比較大,asset pack超過1GB的話,那你可能有一些額外步驟要做。
PAD的3種delivery mode
PAD會將你的App裡部分assets拆出來變成asset packs,而asset packs有3種不同的模式:
install-time
: 在使用者從Play store下載應用程式時,會自動跟著一起被下載。基本上被視為App不可分割的一部份,會增加Play Store上面列出的App檔案大小。App在啟動時就已經可以使用這些asset packs。
fast-follow
: 使用者安裝完App後才開始下載,有可能在使用者啟動App時,fast-follow的asset packs還沒下載完成。
on-demand
: 不會自動被下載,必須在code裡去call API來下載
PAD大小限制
install-time
的大小上限為 1 GBfast-follow
和on-demand
的上限為各 512 MB- 每個 AAB 裡所有 asset packs 的總大小上限為 2GB
- 每個 AAB 最多能有 50 個 asset packs
Unity怎麼自動產生 asset packs 的?
Unity將AAB拆成 base module
跟 asset packs
。
base module
: 包含程式碼、plugins、還有第一個scene中的所有assets。第一個scene就是在build settings中最上面的、index為0的scene。
asset packs
: 剩下的全部assets會被包在這裡。
如果asset packs的總大小在 1 GB 以下,Unity會將它全部塞到 install-time
裡面,這樣是最方便的
如果超過 1 GB,Unity會將streaming assets裡的檔案包成一包,剩下的assets包成另一包。比較小的那包會設定成fast-follow
,比較大的那包會是 install-time
注意上面提到的PAD大小限制,所以使用Unity自動產生的 asset packs 大小總和最大就只能到 1.5 GB,再多就要使用自訂的 asset packs 了。
檢查 Unity 產生的 asset packs 狀態
如果你的App有使用到 fast-follow
或 on-demand
的 asset packs,則需要在使用它們前確認他們是否已經下載完成了
在程式碼中call AndroidAssetPacks.coreUnityAssetPacksDownloaded
可以檢查是否所有 Unity 自動產生的 asset packs 都被下載完成了
AndroidAssetPacks.GetCoreUnityAssetPackNames
可以用來獲取所有 Unity 產生的 asset packs 名稱,再使用 AndroidAssetPacks.GetAssetPackStateAsync
可以檢查單一 asset packs 的狀態 AndroidAssetPacks.DownloadAssetPackAsync
則可以用來啟動下載
使用自訂的 asset packs
應該很少人會走到這步,但 Unity 也提供你自訂 asset packs 的選項。
當你的 asset packs 總大小介於 1.5 ~ 2 GB 時,就無法使用Unity的自動分包了。
使用自訂 asset packs 的方法為新增一個資料夾並使用 .androidpack
作為副檔名,在裡頭放需要的 assets,該資料夾就會被打包成一個 asset pack。
預設的 delivery mode 是 on-demand
,如果要改變,新增一個名為 build.gradle
的檔案到自訂 asset packs 資料夾底下,貼上以下內容:
apply plugin: 'com.android.asset-pack'
assetPack {
packName = "自訂asset pack的資料夾名稱"
dynamicDelivery {
deliveryType = "fast-follow"
}
}
這會將 delivery mode 改成 fast-follow
,其他詳細內容請參考 Unity官方文檔
(2) 使用Google提供的Play Plugins for Unity
除了使用 Unity 內建的功能,Google也有推出可以支援使用PAD的Unity Plugins,部分Unity內建的PAD功能也是使用此Plugin的一些API實現的
支援的Unity版本:
- 2018.4以上即可
與方法(1)不同,此方法不需要將Unity更新至最新的小版本即可使用。
步驟1: 安裝 Play Plugins for Unity
從這裡下載 .unitypackage
來安裝plugins,也可以透過 Package Manager 匯入,但會比較麻煩一點。
步驟2 : 調整 Asset Delivery Settings
匯入Plugin完成後,Unity編輯器上方選單會多出一個 “Google”。點進去 Google -> Android App Bundle -> Asset Delivery Settings,然後把"Separate Base APK Assets" 打勾
點選 Google -> Build Android App Bundle 即可。注意一定要從這邊Build,如果使用Unity原本的 File -> Build Settings -> Build,會沒有效果。
Play Plugins會自動將所有assets(包括Scene0)分包到 install-time
的 asset pack 中,所以最大檔案限制一樣是 1 GB
使用自訂的 asset packs
Play Plugins一樣也提供自訂的 asset packs,但與Unity內建的不同,Play Plugins自訂的 asset packs裡頭的 assets 必須是 AssetBundle 的形式才行
在Google -> Android App Bundle -> Asset Delivery Settings中,將包含AssetBundle的資料夾加進列表中,並設定相關的delivery mode,如下圖
其他詳細的內容可以參考 Google Play 官方文件
曾踩到的一些坑分享:
1: 如果你的專案中有導入 Firebase 套件,使用Play Plugins可能會導致無法啟動的錯誤,建議使用 Unity 內建的 PAD 功能
2: 如果 App 開啟後直接閃退,可以參考這個暫時的解法,在 Play Plugins 的原始碼中加入那兩行有機會解決這問題
從官方 repo issue 的量跟多元程度可以看的出來,Google Play Unity Plugins 還不是很穩定,如果你的專案比較複雜的話,使用前要三思。
如何測試用Play Asset Delivery建置出的AAB檔案
一般的 APK 檔案只要丟到 Android 手機裡然後直接點選安裝就可以了,但 AAB 檔案無法這麼做,那我們要如何檢查 Build 出來的 AAB 檔案是否正常?
方法主要有3個,建議由上到下3個方法都跑過一遍確定沒問題再上production環境
- 使用 Android Studio 查看 (最快)
- 使用 bundletool 安裝 (方便)
- 上傳至 Play Console 測試 (最接近真實情況)
(1) 使用 Android Studio 查看
Build出來的AAB檔案,直接拖曳到Android Studio中,就能看到他的結構。
如果有正確啟用 Play Asset Delivery,可以觀察到有一個UnityDataAssetPack
,它就是被分包成 install-time
的 asset pack,可以從欄位中的Download Size觀察它的檔案大小
而base
就是包含code等執行檔的初始App,注意 base
的總大小一樣是不能超過 150 MB 的。
如果你是用 Google Play Plugins 去做分包的,會略有不同,asset pack 的名稱會是 base_assets
(2) 使用 bundletool 安裝
bundletool 是 Google 提供的一個工具,有了它我們就可以將 AAB 透過電腦安裝到 Android 裝置中
安裝 bundletool 的方式,以下二擇一即可
- 使用homebrew (macOS 限定)
$brew install bundletool
2. 從官方 repo 下載 .jar 檔案
從這裡下載bundletool-all-1.8.0.jar,或其他最新版本。要確認你的環境裡已經安裝 Java 才能使用。
然後將你的 Android 裝置透過 USB 線連接到電腦,或是啟動Android Studio的模擬器
在終端機輸入以下指令:
中括號[]裡的內容包含中括號本身須替換成你電腦上的位置
$bundletool build-apks \
--bundle=[AAB檔案的路徑含副檔名] \
--output=[要輸出APKS檔案到哪個路徑含副檔名] \
--ks=[Android KeyStore檔案路徑] \
--ks-pass=pass:"[KeyStore密碼]" \
--ks-key-alias="[Key Alias]" \
--key-pass=pass:"[Key Alias密碼]"
如果你是從官方 repo 下載 .jar 檔案的方式,bundletool 要替換成 java -jar bundletool-all-1.8.0.jar
build-apks 成功後,在輸出路徑可以找到 .apks 檔案,這個還不是可以直接安裝於 Android 裝置上的檔案。
再於終端機輸入以下指令:
$bundletool install-apks \
--apks=[剛輸出的APKS檔案路徑] \
--adb=[adb路徑]
adb是Android Debug用的工具,默認會跟Android Studio一起安裝於電腦中。以我的例子來說路徑是在 /Users/cloudlin/Library/Android/sdk/platform-tools/adb
完成以上的步驟後,可以發現連接的 Android 裝置已經安裝好你的App了,可以開始測試了!
(3) 上傳至 Play Console 測試
在 Play Console測試會是最接近使用者從Google Play商店下載的真實情況,但需要等待的時間也會比較長(等待上傳、等待Play Store檢查App、對App做設定…等),建議在最後進行此測試即可。
登入你的Google Play Console後,選擇"建立應用程式",如果已經建立過了,直接點進建立好的應用程式頁面。
點進左邊側邊欄的"應用程式套件探索工具",點選右上角的"上傳新版本"
上傳後點進去該版本,尋找"供應"的標籤頁,可以看到 base
為App本體,”Asset packs” 底下會列出所有的 asset packs 內容,也可以看到它的檔案大小
若想從Play Store上安裝測試版,可以從"下載內容"的頁籤中,點選"複製分享連結",然後從 Android 裝置上打開此連結,即可模擬從 Play Store 上下載的情況。
以上就是本次的分享,在撰文的這個時間點, Play Asset Delivery 在 Unity 中仍是一個很新的功能 (2021/07/27才新增到Unity中),所以穩定性仍然是差了些,遇到的坑可能會比較多(視乎你專案的複雜度)。相信這些在時間推移後,會有更好的體驗。