یکپارچه سازی تحویل دارایی (Unity)

هنگام ادغام تحویل دارایی، بازی‌های Unity می‌توانند با استفاده از Addressables یا AssetBundles به بسته‌های دارایی دسترسی داشته باشند. Addressable ها راه حل های جدیدتر و توصیه شده برای تحویل دارایی برای بازی های ساخته شده با Unity 2019.4 یا بالاتر هستند، در حالی که AssetBundles از بسته های دارایی در Unity 2017.4 و 2018.4 پشتیبانی می کند.

Unity Addressables

بازی‌های ساخته شده با Unity 2019.4 یا بالاتر باید از Addressables برای تحویل دارایی در Android استفاده کنند. Unity یک API Play Asset Delivery (PAD) برای مدیریت بسته‌های دارایی Android با استفاده از Addressables ارائه می‌کند. برای اطلاعات در مورد استفاده از Addressable ها به موارد زیر مراجعه کنید:

از فایل های AssetBundle استفاده کنید

بازی‌های ساخته شده با Unity 2017.4 و 2018.4 می‌توانند از فایل‌های AssetBundle برای تحویل دارایی در اندروید استفاده کنند. فایل‌های Unity AssetBundle حاوی دارایی‌های سریالی هستند که می‌توانند در حین اجرای برنامه توسط موتور Unity بارگیری شوند. این فایل‌ها مختص پلتفرم هستند (مثلاً برای اندروید ساخته شده‌اند) و می‌توانند در ترکیب با بسته‌های دارایی استفاده شوند. معمولاً، یک فایل AssetBundle در یک بسته دارایی واحد بسته بندی می شود که بسته از همان نام AssetBundle استفاده می کند. اگر می‌خواهید در ایجاد بسته دارایی انعطاف‌پذیری بیشتری داشته باشید، بسته دارایی را با استفاده از API پیکربندی کنید.

در زمان اجرا، از کلاس Play Asset Delivery for Unity برای بازیابی AssetBundle بسته بندی شده در یک بسته دارایی استفاده کنید.

پیش نیازها

  1. آخرین نسخه پلاگین Play Asset Delivery Unity را از بسته های Google برای Unity دانلود کنید.

  2. AssetBundles را در Unity ایجاد کنید .

AssetBundles را با استفاده از UI پیکربندی کنید

  1. هر AssetBundle را در یک بسته دارایی پیکربندی کنید:

    1. Google > Android App Bundle > تنظیمات تحویل دارایی را انتخاب کنید.
    2. برای انتخاب پوشه‌هایی که مستقیماً حاوی فایل‌های AssetBundle هستند، روی Add Folder کلیک کنید.

  2. برای هر بسته، حالت تحویل را به زمان نصب ، دنبال کردن سریع یا درخواستی تغییر دهید. هر گونه خطا یا وابستگی را برطرف کنید و پنجره را ببندید.

  3. Google > Build Android App Bundle را برای ساختن بسته نرم افزاری انتخاب کنید.

  4. (اختیاری) بسته نرم افزاری خود را برای پشتیبانی از فرمت های مختلف فشرده سازی بافت پیکربندی کنید.

بسته‌های دارایی را با استفاده از 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);
}

با توجه به BuildPlayerOptions و AssetPackConfig می‌توانید از روش استاتیک BuildBundle در کلاس Bundletool برای ایجاد یک Android App Bundle با بسته‌های دارایی استفاده کنید.

برای یک آموزش راهنما، به استفاده از Play Asset Delivery در بازی‌های Unity Codelab مراجعه کنید.

ادغام با Play Asset Delivery Unity API

Play Asset Delivery Unity API عملکردی را برای درخواست بسته‌های دارایی، مدیریت دانلودها و دسترسی به دارایی‌ها ارائه می‌کند. حتما ابتدا افزونه Unity را به پروژه خود اضافه کنید .

عملکردهایی که در API استفاده می کنید به نحوه ایجاد بسته های دارایی بستگی دارد.

اگر بسته‌های دارایی را با استفاده از رابط کاربری افزونه ایجاد کرده‌اید ، بسته‌های دارایی پیکربندی شده با افزونه را انتخاب کنید.

اگر بسته‌های دارایی را با استفاده از API (یا رابط کاربری افزونه) ایجاد کرده‌اید ، بسته‌های دارایی پیکربندی‌شده با API را انتخاب کنید.

شما API را با توجه به نوع تحویل بسته دارایی که می خواهید به آن دسترسی داشته باشید پیاده سازی کنید. این مراحل در فلوچارت زیر نشان داده شده است.

نمودار جریان بسته دارایی برای افزونه

شکل 1. نمودار جریان برای دسترسی به بسته های دارایی

AssetBundles را بازیابی کنید

کتابخانه 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 مگابایت می‌توانند به‌طور خودکار بارگیری شوند، اما فقط از طریق 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;
    }
}

لغو درخواست (فقط درخواستی)

اگر می‌خواهید قبل از بارگیری AssetBundles در حافظه، درخواست را لغو کنید، متد AttemptCancel() را در شی PlayAssetBundleRequest فراخوانی کنید:

// 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.
}

بسته های دارایی را به صورت ناهمزمان درخواست کنید

در بیشتر موارد، باید از Coroutines برای درخواست بسته‌های دارایی به صورت ناهمزمان و نظارت بر پیشرفت استفاده کنید، همانطور که در زیر نشان داده شده است:

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();
    }
}

AssetBundles را حذف کنید

می‌توانید 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 آزمایش کنید .