שילוב העברת נכסים (Unity)

כשמשלבים העברת נכסים, משחקי Unity יכולים לגשת לחבילות נכסים באמצעות Addressables או AssetBundles. Addressables הוא הפתרון העדכני והמומלץ להעברת נכסים למשחקים שנוצרו ב-Unity מגרסה 2019.4 ואילך, בעוד ש-AssetBundles תומך בחבילות נכסים ב-Unity מגרסה 2017.4 ו-2018.4.

Unity Addressables

במשחקים שנוצרו ב-Unity מגרסה 2019.4 ואילך, צריך להשתמש ב-Addressables כדי לשלוח נכסים ל-Android. ‏Unity מספקת ממשק API של Play Asset Delivery ‏ (PAD) לטיפול בחבילות נכסים ל-Android באמצעות Addressables. למידע נוסף על השימוש ב-Addressables:

שימוש בקובצי AssetBundle

במשחקים שנוצרו באמצעות Unity 2017.4 ו-2018.4 אפשר להשתמש בקובצי AssetBundle כדי להעביר נכסים ב-Android. קבצים מסוג AssetBundle ב-Unity מכילים נכסים בסריאליזציה שאפשר לטעון במנוע Unity בזמן שהאפליקציה פועלת. הקבצים האלה ספציפיים לפלטפורמה (לדוגמה, הם מפותחים ל-Android) וניתן להשתמש בהם בשילוב עם חבילות נכסים. בדרך כלל, קובץ AssetBundle אחד נארז בחבילת נכסים אחת, והשם של החבילה זהה לשם של AssetBundle. אם אתם רוצים גמישות רבה יותר ביצירת חבילת נכסים, תוכלו להגדיר אותה באמצעות ה-API.

בזמן הריצה, משתמשים בכיתה Play Asset Delivery for Unity כדי לאחזר AssetBundle שארוז בחבילת נכסים.

דרישות מוקדמות

  1. מגדירים את סביבת הפיתוח:

OpenUPM-CLI

אם OpenUPM CLI מותקן, אפשר להתקין את המרשם של OpenUPM באמצעות הפקודה הבאה:

openupm add com.google.play.assetdelivery

OpenUPM

  1. פותחים את הגדרות מנהל החבילות על ידי בחירה באפשרות בתפריט של Unity‏ Edit > Project Settings > Package Manager.

  2. מוסיפים את 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
    
  3. פותחים את תפריט מנהל החבילות על ידי בחירה באפשרות בתפריט של Unity‏ Window (חלון) > Package Manager (מנהל החבילות).

  4. בתפריט הנפתח של היקף הניהול, בוחרים באפשרות My Registries.

  5. בוחרים את החבילה Google Play Integrity plugin for Unity מרשימת החבילות ולוחצים על Install.

ייבוא מ-GitHub

  1. מורידים את הגרסה האחרונה של .unitypackage מ-GitHub.

  2. מייבאים את הקובץ .unitypackage על ידי בחירה באפשרות בתפריט של Unity‏ Assets > Import package > Custom Package (נכסים > ייבוא חבילה > חבילה מותאמת אישית) וייבוא כל הפריטים.

  1. יצירת AssetBundles ב-Unity

הגדרת AssetBundles באמצעות ממשק המשתמש

  1. מגדירים כל AssetBundle בחבילת נכסים:

    1. בוחרים באפשרות Google‏ > Android App Bundle‏ > Asset Delivery Settings.
    2. כדי לבחור תיקיות שמכילות ישירות קובצי AssetBundle, לוחצים על Add Folder.

  2. בכל חבילת מודעות, משנים את Delivery Mode ל-Install Time, ל-Fast Follow או ל-On Demand. מתקנים את השגיאות או יחסי התלות וסוגרים את החלון.

  3. בוחרים באפשרות Google‏ > Build Android App Bundle כדי ליצור את חבילת האפליקציות.

  4. (אופציונלי) מגדירים את חבילת האפליקציות כך שתתמוך בפורמטים שונים של דחיסת טקסטורות.

הגדרת חבילות נכסים באמצעות ה-API

אפשר להגדיר את העברת הנכסים באמצעות סקריפטים של עורכי טקסט, שאפשר להריץ כחלק ממערכת build אוטומטית.

משתמשים בכיתה AssetPackConfig כדי להגדיר אילו נכסים לכלול ב-build של 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);
}

אפשר גם להשתמש ב-method הסטטי BuildBundle בכיתה Bundletool כדי ליצור Android App Bundle עם חבילות נכסים, על סמך BuildPlayerOptions ו-AssetPackConfig.

הדרכה מודרכת מפורטת זמינה במאמר שימוש ב-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 ומפעילים את ה-method‏ 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 והפצה על פי דרישה

הקטעים האלה חלים על חבילות נכסים מסוג 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;
}

הורדות גדולות

אפשר להוריד באופן אוטומטי חבילות נכסים דיגיטליים גדולות מ-200MB, אבל רק דרך 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 נטענים בזיכרון, צריך לבצע קריאה ל-method‏ 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 ומגדירים שיטה להודעה חוזרת (callback) כשהפעולה מסתיימת:

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

אפשר להסיר חבילות נכסים דיגיטליים מסוג 'מעקב מהיר' ו'על פי דרישה' שלא נטענו כרגע לזיכרון. מריצים את הקריאה האסינכרונית הבאה ומגדירים שיטה להודעה חוזרת (callback) כשהיא מסתיימת:

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.