整合資產提供功能時,Unity 遊戲可以使用 Addressable 或 AssetBundle 存取資產包。Addressable 是我們最近建議使用的資產提供解決方案,適用於使用 Unity 2019.4 以上版本建構的遊戲,而 AssetBundle 則支援 Unity 2017.4 和 2018.4 中的資產包。
Unity Addressable
若是使用 Unity 2019.4 以上版本建構的遊戲,應使用 Addressable 在 Android 上提供資產。Unity 提供 Play Asset Delivery (PAD) API,以便使用 Addressable 處理 Android 資產包。如要瞭解如何使用 Addressable,請參閱下列資源:
- Android 套件的 Addressable
- Unity 的 PAD 指南
- Unity 的 PAD API 參考說明文件
使用 AssetBundle 檔案
若是使用 Unity 2017.4 和 2018.4 建構的遊戲,可以使用 AssetBundle 檔案在 Android 上提供資產。Unity 的 AssetBundle 檔案具有序列化的資產,可在應用程式執行時由 Unity 引擎載入。這些檔案依平台而異 (例如專為 Android 建構的檔案),可與資產包搭配使用。大多數情況下,一個 AssetBundle 檔案會封裝成單一資產包,以及名稱與 AssetBundle 相同的套件。如果想更靈活地建立資產包,請使用 API 設定資產包。
請在執行階段,使用 Unity 專屬 Play Asset Delivery 類別擷取封裝於資產包內的 AssetBundle。
必要條件
- 設定開發環境:
OpenUPM-CLI
如果您已安裝 OpenUPM CLI,可以使用下列指令安裝 OpenUPM 登錄:
openupm add com.google.play.assetdelivery
OpenUPM
選取 Unity 選單選項「Edit」>「Project Settings」>「Package Manager」,開啟套件管理工具設定。
將 OpenUPM 新增為 Package Manager 視窗中的有範圍限制的登錄檔:
Name: package.openupm.com URL: https://package.openupm.com Scopes: com.google.external-dependency-manager com.google.play.common com.google.play.core com.google.play.assetdelivery com.google.android.appbundle
選取 Unity 選單選項「Window」>「Package Manager」,即可開啟「package manager」選單。
將管理員範圍下拉式選單設為「我的註冊中心」。
從套件清單中選取「Google Play Integrity 外掛程式 (適用於 Unity)」套件,然後按下「Install」。
從 GitHub 匯入
從 GitHub 下載最新的
.unitypackage
版本。選取 Unity 選單選項「Assets」>「Import package」>「Custom Package」,然後匯入所有項目,即可匯入
.unitypackage
檔案。
透過 UI 設定 AssetBundle
設定資產包中的各項 AssetBundle:
- 依序選取「Google」>「Android App Bundle」>「Asset Delivery Settings」。
- 若要直接選取含有 AssetBundle 檔案的資料夾,請按一下「Add Folder」。
將每個套件的「Delivery Mode」變更為「Install Time」、「Fast Follow」或「On Demand」。解決任何錯誤或依附元件,接著關閉視窗。
依序選取「Google」>「Build Android App Bundle」,建立應用程式套件。
(選用) 調整應用程式套件的設定,支援不同的紋理壓縮格式。
使用 API 設定資產包
您可以透過編輯器指令碼設定資產提供功能,該指令碼可做為自動建構系統的一部分執行。
請使用 AssetPackConfig
類別,定義要在 Android App Bundle 版本中加入哪些資產,並定義資產提供模式。這些資產包不需要包含 AssetBundle。
public void ConfigureAssetPacks { // Creates an AssetPackConfig with a single asset pack, named // examplePackName, containing all the files in path/to/exampleFolder. var assetPackConfig = new AssetPackConfig(); assetPackConfig.AddAssetsFolder("examplePackName", "path/to/exampleFolder", AssetPackDeliveryMode.OnDemand); // Configures the build system to use the newly created assetPackConfig when // calling Google > Build and Run or Google > Build Android App Bundle. AssetPackConfigSerializer.SaveConfig(assetPackConfig); // Alternatively, use BundleTool.BuildBundle to build an App Bundle from script. BuildBundle(new buildPlayerOptions(), assetPackConfig); }
您也可以使用 Bundletool
類別中的靜態 BuildBundle
方法,產生內含資產包的 Android App Bundle,但前提是要有 BuildPlayerOptions 和 AssetPackConfig
。
如需輔助教學文件,請參閱在 Unity 遊戲程式碼研究室中使用 Play Asset Delivery 一文。
與 Play Asset Delivery Unity API 整合
Play Asset Delivery Unity API 提供的功能包括要求資產包、管理下載內容及存取資產等。請務必先將 Unity 外掛程式新增至專案。
您使用 API 的功能取決於您建立資產包的方式。
如果您使用外掛程式 UI 建立資產包,請選取「外掛程式設定的資產包」。
如果您使用 API (或外掛程式 UI) 建立資產包,請選取「API 設定的資產包」。
您可以根據想要存取的資產包的傳遞類型來實作 API。步驟請參見下方流程圖。
擷取 AssetBundle
匯入 Play Asset Delivery 程式庫並呼叫 RetrieveAssetBundleAsync()
方法,以擷取 AssetBundle。
using Google.Play.AssetDelivery; // Loads the AssetBundle from disk, downloading the asset pack containing it if necessary. PlayAssetBundleRequest bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(asset-bundle-name);
安裝時提供
設定為 install-time
的資產包可在應用程式啟動時立即使用。您可以使用以下方法從 AssetBundle 載入一種情境:
AssetBundle assetBundle = bundleRequest.AssetBundle; // You may choose to load scenes from the AssetBundle. For example: string[] scenePaths = assetBundle.GetAllScenePaths(); SceneManager.LoadScene(scenePaths[path-index]);
快速追蹤及隨選傳遞
這部分的內容適用於 fast-follow
及 on-demand
資產包。
檢查狀態
每個資產包會儲存在應用程式內部儲存空間的獨立資料夾中。使用 isDownloaded()
方法判斷是否已下載資產包。
監控下載內容
查詢 PlayAssetBundleRequest
物件以監控要求的狀態:
// Download progress of request, between 0.0f and 1.0f. The value will always be // 1.0 for assets delivered as install-time. // NOTE: A value of 1.0 will only signify the download is complete. It will still need to be loaded. float progress = bundleRequest.DownloadProgress; // Returns true if: // * it had either completed the download, installing, and loading of the AssetBundle, // * OR if it has encountered an error. bool done = bundleRequest.IsDone; // Returns status of retrieval request. AssetDeliveryStatus status = bundleRequest.Status; switch(status) { case AssetDeliveryStatus.Pending: // Asset pack download is pending - N/A for install-time assets. case AssetDeliveryStatus.Retrieving: // Asset pack is being downloaded and transferred to app storage. // N/A for install-time assets. case AssetDeliveryStatus.Available: // Asset pack is downloaded on disk but NOT loaded into memory. // For PlayAssetPackRequest(), this indicates that the request is complete. case AssetDeliveryStatus.Loading: // Asset pack is being loaded. case AssetDeliveryStatus.Loaded: // Asset pack has finished loading, assets can now be loaded. // For PlayAssetBundleRequest(), this indicates that the request is complete. case AssetDeliveryStatus.Failed: // Asset pack retrieval has failed. case AssetDeliveryStatus.WaitingForWifi: // Asset pack retrieval paused until either the device connects via Wi-Fi, // or the user accepts the PlayAssetDelivery.ShowConfirmationDialog dialog. case AssetDeliveryStatus.RequiresUserConfirmation: // Asset pack retrieval paused until the user accepts the // PlayAssetDelivery.ShowConfirmationDialog dialog. default: break; }
大型下載內容
大小超過 200 MB 的資產包只有在與 Wi-Fi 連線時才會自動下載。如果使用者未連上 Wi-Fi,PlayAssetBundleRequest
狀態會設為 AssetDeliveryStatus.WaitingForWifi
,下載作業也會暫停。在此情況下,請等到裝置連線至 Wi-Fi 後再繼續下載,或提示使用者允許透過行動網路連線下載資產包。
需要使用者確認
如果套件具有 AssetDeliveryStatus.RequiresUserConfirmation
狀態,使用者必須接受顯示 PlayAssetDelivery.ShowConfirmationDialog()
的對話方塊,下載作業才會繼續進行。如果 Play 無法辨識應用程式,就會出現這個狀態。請注意,在這種情況下呼叫 PlayAssetDelivery.ShowConfirmationDialog()
會導致應用程式更新。更新完成後,請再次要求素材資源。
if(request.Status == AssetDeliveryStatus.RequiresUserConfirmation || request.Status == AssetDeliveryStatus.WaitingForWifi) { var userConfirmationOperation = PlayAssetDelivery.ShowConfirmationDialog(); yield return userConfirmationOperation; switch(userConfirmationOperation.GetResult()) { case ConfirmationDialogResult.Unknown: // userConfirmationOperation finished with an error. Something went // wrong when displaying the prompt to the user, and they weren't // able to interact with the dialog. case ConfirmationDialogResult.Accepted: // User accepted the confirmation dialog--an update will start. case ConfirmationDialogResult.Declined: // User canceled or declined the dialog. It can be shown again. default: break; } }
取消要求 (僅限隨選)
若要在 AssetBundle 載入記憶體之前取消要求,請在 PlayAssetBundleRequest
物件上呼叫 AttemptCancel()
方法:
// Will only attempt if the status is Pending, Retrieving, or Available - otherwise // it will be a no-op. bundleRequest.AttemptCancel(); // Check to see if the request was successful by checking if the error code is Canceled. if(bundleRequest.Error == AssetDeliveryErrorCode.Canceled) { // Request was successfully canceled. }
以非同步方式要求資產包
在多數情況下,您應使用協同程式,以非同步方式要求資產包並監控進度,如下所示:
private IEnumerator LoadAssetBundleCoroutine(string assetBundleName) { PlayAssetBundleRequest bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(assetBundleName); while (!bundleRequest.IsDone) { if(bundleRequest.Status == AssetDeliveryStatus.WaitingForWifi) { var userConfirmationOperation = PlayAssetDelivery.ShowCellularDataConfirmation(); // Wait for confirmation dialog action. yield return userConfirmationOperation; if((userConfirmationOperation.Error != AssetDeliveryErrorCode.NoError) || (userConfirmationOperation.GetResult() != ConfirmationDialogResult.Accepted)) { // The user did not accept the confirmation. Handle as needed. } // Wait for Wi-Fi connection OR confirmation dialog acceptance before moving on. yield return new WaitUntil(() => bundleRequest.Status != AssetDeliveryStatus.WaitingForWifi); } // Use bundleRequest.DownloadProgress to track download progress. // Use bundleRequest.Status to track the status of request. yield return null; } if (bundleRequest.Error != AssetDeliveryErrorCode.NoError) { // There was an error retrieving the bundle. For error codes NetworkError // and InsufficientStorage, you may prompt the user to check their // connection settings or check their storage space, respectively, then // try again. yield return null; } // Request was successful. Retrieve AssetBundle from request.AssetBundle. AssetBundle assetBundle = bundleRequest.AssetBundle;
若要進一步瞭解如何處理錯誤,請參閱 AssetDeliveryErrorCodes
清單。
其他 Play Core API 方法
以下列出一些其他您可能想在應用程式中使用的 API 方法。
檢查下載內容的大小
如要檢查 AssetBundle 大小,請對 Google Play 發出非同步呼叫,並設定作業完成後的回呼方法:
public IEnumerator GetDownloadSize() { PlayAsyncOperation<long> getSizeOperation = PlayAssetDelivery.GetDownloadSize(assetPackName); yield return getSizeOperation; if(operation.Error != AssetDeliveryErrorCode.NoError) { // Error while retrieving download size. } else { // Download size is given in bytes. long downloadSize = operation.GetResult(); } }
移除 AssetBundle
您可以移除目前尚未載入記憶體的快速追蹤及隨選 AssetBundle。請進行以下非同步呼叫,並設定完成時的回呼方法:
PlayAsyncOperation<string> removeOperation = PlayAssetDelivery.RemoveAssetPack(assetBundleName); removeOperation.Completed += (operation) => { if(operation.Error != AssetDeliveryErrorCode.NoError) { // Error while attempting to remove AssetBundles. } else { // Files were deleted OR files did not exist to begin with. } };
後續步驟
在本機和 Google Play 中測試 Asset Delivery。