整合 Asset Delivery (Unity)

請按照本指南中的步驟,從您的 Unity C# 程式碼存取應用程式的資產包。

建構以用於 Unity

Unity 的 AssetBundle 檔案具有序列化的資產,可在應用程式執行時由 Unity 引擎載入。這些檔案依平台而異(例如 Android 專用),可與資產包共同使用。大多數情況下,一個 AssetBundle 檔案會封裝成單一的資產包,以及使用與 AssetBundle 相同名稱的套件。如果想更靈活地建立資產包,請使用 API 設定資產包

在執行階段,使用 Unity 專屬 Play Asset Delivery 類別擷取封裝於資產包內的 AssetBundle。

必要條件

  1. 取得 Play Asset Delivery 的 Unity 外掛程式(或套件)

  2. 在 Unity 中建立 AssetBundle

透過 UI 設定 AssetBundle

  1. 設定資產包中的各項 AssetBundle:

    1. 選擇「Google」>「Android App Bundle」>「Asset Delivery 設定」。
    2. 若要直接選取具有 AssetBundle 檔案的資料夾,請按一下「新增資料夾」。

  2. 將每個套裝組合的「交付模式」變更為「安裝時間」、「快速追蹤」或「隨選」。解決任何錯誤或依附元件,接著關閉視窗。

  3. 選擇「Google」>「建立 Android App Bundle」建立應用程式套件。

  4. (選用)設定您的應用程式套件以支援不同的紋理壓縮格式

使用 API 設定資產包

您可以透過編輯器指令碼設定 Asset Delivery,該指令碼可以作為自動建構系統的一部分執行。

使用 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 以及資產包,前提是 BuildPlayerOptionsAssetPackConfig

如需輔助教學文件,請參閱在 Unity 遊戲程式碼研究室中使用 Play Asset Delivery 一文。

與 Play Asset Delivery Unity API 整合

Play Asset Delivery Unity API 提供的功能包括要求資產包、管理下載內容及存取資產等。請務必先新增 Unity 外掛程式至您的專案中。

您使用 API 的功能取決於您建立資產包的方式。

如果您 使用外掛程式 UI 建立資產包, 請選擇外掛程式設定的資產包

如果您 使用 API(或外掛程式 UI)建立資產包, 請選擇 API 設定的資產包

您可以根據想要存取的資產包的傳遞類型來實作 API。步驟請參見下方流程圖。

外掛程式的資產包流程圖

圖 1. 存取資產包的流程圖

擷取 AssetBundle

匯入 Play Asset Delivery 程式庫並呼叫 RetrieveAssetBundleAsync() 方法,以擷取 Asset Bundle。

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-followon-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.ShowCellularDataConfirmation dialog.
    default:
        break;
}

大型下載內容

大小超過 150 MB 的資產包只有在與 Wi-Fi 連線時才會自動下載。如果使用者未連接 Wi-Fi,PlayAssetBundleRequest 狀態會設為 AssetDeliveryStatus.WaitingForWifi,下載將暫停。在此情況下,請等到裝置連線至 Wi-Fi 後繼續下載,或提示使用者允許透過行動數據連線下載資產包。

if(bundleRequest.Status == AssetDeliveryStatus.WaitingForWifi) {
    var userConfirmationOperation = PlayAssetDelivery.ShowCellularDataConfirmation();
    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. In this case, we recommend
            // developers wait for Wi-Fi before attempting to download again.
            // You can get more info by calling GetError() on the operation.
        case ConfirmationDialogResult.Accepted:
            // User accepted the confirmation dialog - download will start
            // automatically (no action needed).
        case ConfirmationDialogResult.Declined:
            // User canceled or declined the dialog. Await Wi-Fi connection, or
            // re-prompt the user.
        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 方法。

檢查下載內容的大小

請對 Google Play 發出非同步呼叫來檢查 AssetBundle 的大小,並設定作業完成後的回呼方法:

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