שילוב העברת נכסים (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‏ נכסים > ייבוא חבילה > חבילה מותאמת אישית וייבוא כל הפריטים.

  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 דומה ללא קשר לסוג המסירה של חבילת הנכסים שרוצים לגשת אליה. השלבים האלה מוצגים בתרשים התהליך הבא.

תרשים תהליך של חבילת נכסים ל-API

איור 1. תרשים זרימה לגישה לחבילות של נכסים

אחזור של חבילת נכסים

מייבאים את ספריית Play Asset Delivery ומפעילים את השיטה RetrieveAssetPackAsync() כדי להוריד חבילת נכסים, אם הגרסה האחרונה של החבילה עדיין לא זמינה בדיסק.

using Google.Play.AssetDelivery;

// After download, the assets and/or AssetBundles contained in the asset pack
// are not loaded into memory.
PlayAssetPackRequest request = PlayAssetDelivery.RetrieveAssetPackAsync(assetPackName);

העברה בזמן ההתקנה

חבילת נכסים שמוגדרת כ-install-time זמינה באופן מיידי עם הפעלת האפליקציה, אבל צריך לטעון את הנכסים שלה לזיכרון. למידע נוסף, ראו טעינה של נכסים לזיכרון.

הפצה ב-fast follow והפצה על פי דרישה

הקטעים האלה חלים על חבילות נכסים מסוג fast-follow ו-on-demand.

בדיקת הסטטוס

כל חבילת נכסים מאוחסנת בתיקייה נפרדת באחסון הפנימי של האפליקציה. משתמשים ב-method‏ isDone() כדי לקבוע אם חבילת נכסים כבר הורדה וזמינה, או אם אירעה שגיאה.

מעקב אחר ההורדה

שולחים שאילתה לאובייקט PlayAssetPackRequest כדי לעקוב אחרי הסטטוס של הבקשה:

// 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 does not mean that the request has completed, only that
// the DOWNLOADING stage is finished.
float progress = request.DownloadProgress;

// Returns the status of the retrieval request.
// If the request completed successfully, this value should be AssetDeliveryStatus.Available.
// If an error occurred, this value should be AssetDeliveryStatus.Failed.

AssetDelivery status = request.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.Failed:
        // Asset pack retrieval 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;
}

// Returns true if status is AssetDeliveryStatus.Available or AssetDeliveryStatus.Failed.
bool done = request.IsDone;

// If AssetDeliveryStatus.Failed, find more info about the error.
AssetDeliveryErrorCode error = request.Error;

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

אפשר להוריד באופן אוטומטי חבילות נכסים גדולות מ-200MB, אבל רק אם המכשיר מחובר לרשת Wi-Fi. אם המשתמש לא מחובר לרשת Wi-Fi, המצב של PlayAssetPackRequest מוגדר ל-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;
    }
}

ביטול בקשה (על פי דרישה בלבד)

אם אתם צריכים לבטל את הבקשה לפני שההורדה של חבילות הנכסים תסתיים, תוכלו להפעיל את השיטה AttemptCancel() באובייקט PlayAssetPackRequest:

// Will only attempt if the status is Pending, Retrieving, or Available; otherwise
// it will be a no-op.
request.AttemptCancel();

// Check to see if the request was successful by checking if the error code is Canceled.
if(request.Error == AssetDeliveryErrorCode.Canceled) {
    // Request was successfully canceled.
}

טעינת נכסים בזיכרון

אחרי שהבקשה תושלם, תוכלו להשתמש באחת מהפונקציות הבאות כדי לטעון את הנכסים לזיכרון:

שליחת בקשה לאסימונים של חבילות נכסים באופן אסינכרוני

ברוב המקרים, כדאי להשתמש ב-Coroutines כדי לבקש חבילות נכסים באופן אסינכרוני ולעקוב אחרי ההתקדמות, כפי שמתואר בהמשך:

private IEnumerator LoadAssetPackCoroutine(string assetPackName) {

    PlayAssetPackRequest request =
        PlayAssetDelivery.RetrieveAssetPackAsync(assetPackName);

    while (!request.IsDone) {
        if(request.Status == AssetDeliveryStatus.WaitingForWifi) {
            var userConfirmationOperation = PlayAssetDelivery.ShowConfirmationDialog();

            // 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(() => request.Status != AssetDeliveryStatus.WaitingForWifi);
        }

        // Use request.DownloadProgress to track download progress.
        // Use request.Status to track the status of request.

        yield return null;
    }

    if (request.Error != AssetDeliveryErrorCode.NoError) {
        // There was an error retrieving the pack. 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. Load the asset pack into memory.
    AssetBundleCreateRequest assetBundleCreateRequest = request.LoadAssetBundleAsync(path/to/exampleBundle);
    yield return assetBundleCreateRequest;
    AssetBundle assetBundle = assetBundleCreateRequest.assetBundle;

מידע נוסף על טיפול בשגיאות זמין ברשימת קודי השגיאה.

שיטות אחרות של Play Core API

בהמשך מפורטות כמה שיטות API נוספות שאפשר להשתמש בהן באפליקציה.

אחזור של כמה חבילות של נכסים

כדי לאחזר כמה חבילות נכסים בבת אחת, משתמשים בפונקציה הבאה:

// assetPackNames is an array of strings corresponding to asset packs.
PlayAssetPackBatchRequest batchRequest = PlayAssetDelivery.RetrieveAssetPackBatchAsync(<IListstring> assetPackNames);

כדי לעקוב אחרי הסטטוסים של כל בקשה, בודקים את Dictionary של המצבים:

// Dictionary of AssetPackStates, with the asset pack name as the key.
Dictionary<string, PlayAssetPackRequest> requests = batchRequest.Requests;

// Returns true if all requests are complete.
bool requestComplete = batchRequest.IsDone;

בדיקת גודל ההורדה

כדי לבדוק את הגודל של חבילת נכסים, מבצעים קריאה אסינכררונית ל-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.