Version: 2017.1
Сборка плагина для iOS
Настройка WWW запросов на iOS

Подготовка вашего приложения для “In App Purchases” (внутриигровые покупки)

Эта глава не описывает, как интегрировать вашу игру с StoreKit API от Apple. Предполагается, что у вас уже есть интеграция с StoreKit через плагин нативного кода.

The Apple StoreKit documentation defines four kinds of products that can be sold via the In App Purchase process:

  • Контент
  • Функционал
  • Услуги
  • Подписки

Эта глава покрывает только первый случай, и, по большей части, концентрируется на концепте скачиваемого контента (downloadable content - DLC). Для реализации DLC в Unity рекомендуются AssetBundles. В данном разделе будет рассказано про создание и использование AssetBundles.

Экспорт ваших ассетов для использования на iOS

Иногда бывает полезным поддерживать раздельные проекты для вашего главного приложения и скачиваемых AssetBundles, которые оно использует. Однако вам следует учесть, что все скрипты на которые ссылаются объекты в AssetBundle должны находиться в исполнительном файле главного проекта. У проекта, который вы используете для создания AssetBundle, в качестве цели сборки должен быть выбран iOS, т.к. содержимое AssetBundle файлов не совместимо между iOS и другими платформами.

AssetBundles создаются используя скрипты редактора - простой пример дан ниже:-

// C#
using UnityEngine;
using UnityEditor;

public class ExportBundle : MonoBehaviour {
    [MenuItem ("Assets/Build AssetBundle From Selection - Track dependencies")]
    static void DoExport() {
        string str = EditorUtility.SaveFilePanel("Save Bundle...", Application.dataPath, Selection.activeObject.name, "assetbundle");
        if (str.Length != 0) {
            BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, str, BuildAssetBundleOptions.CompleteAssets, BuildTarget.iPhone);
        }
    }
}

// JS
@MenuItem ("Assets/Build AssetBundle From Selection - Track dependencies")
static function ExportBundle() {
    var str : String = EditorUtility.SaveFilePanel("Save Bundle...", Application.dataPath, Selection.activeObject.name, "assetbundle");
    if (str.Length != 0) {
        BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, str, BuildAssetBundleOptions.CompleteAssets, BuildTarget.iPhone);
    }
}

Вам следует сохранить этот код в файл, названный ExportBundle, и поместить его в папку названную Editor (вы можете её создать, если в вашем проекте такой ещё нету). Скрипт добавит элемент меню, подписанный “Build AssetBundle From Selection - Track dependencies”, в меню редактора “Assets”.

Контент, который вы хотите включить в Bundle, должен быть подготовлен в форме префабов. Выберите префаб в окне Project View, а затем выберите Assets > Build AssetBundle From Selection - Track dependencies (т.е. элемент меню, добавленный скриптом ExportBundle). Эта команда вызовет диалоговое окно сохранения, где вы сможете выбрать имя и местоположение вашего AssetBundle файла.

Загрузка ваших ассетов на iOS

На заметку: Apple может изменить положение папки, куда вам разрешено записывать данные. Всегда проверяйте последнюю документацию Apple, чтобы быть уверенным, что ваше приложение ей соответствует. Следующий совет был корректен на начало 2013 года.

AssetBundles можно загрузить используя класс WWW и, как только передача будет завершена, доступ к ассетам может быть получен. Рекомендуется скачивать AssetBundle используя LoadFromCacheOrDownload, как показано в следующем отрывке:-

// C#
IEnumerator GetAssetBundle() {
    WWW download;
    string url = "http://somehost/somepath/someassetbundle.assetbundle";

    while (!Caching.ready)
        yield return null;

    download = WWW.LoadFromCacheOrDownload(url, 0);

    yield return download;

    AssetBundle assetBundle = download.assetBundle;
    if (assetBundle != null) {
        // Alternatively you can also load an asset by name (assetBundle.Load("my asset name"))
        Object go = assetBundle.mainAsset;
            
        if (go != null)
            Instantiate(go);
        else
            Debug.Log("Couldn't load resource");    
    } else {
        Debug.Log("Couldn't load resource");    
    }
}

// JS
function GetAssetBundle() {
    var download : WWW;
    var url = "http://somehost/somepath/someassetbundle.assetbundle";
    var download = WWW.LoadFromCacheOrDownload (url, 0);

    yield download;

    var assetBundle = download.assetBundle;
    if (assetBundle != null) {
        // Alternatively you can also load an asset by name (assetBundle.Load("my asset name"))
        var go : Object = assetBundle.mainAsset;
            
        if (go != null)
            Instantiate(go);
        else
            Debug.Log("Couldn't load resource");    
    } else {
        Debug.Log("Couldn't load resource");    
    }
}

Загруженные AssetBundle файлы хранятся в песочнице iOS приложения в папке Library, и на них установлен флажок No Backup. Это значит, что система случайно не удалит эти файлы и их резервные копии не будут созданы в iCloud. Вполне себе хорошая идея установить низкий лимит размера кэша, чтобы ваше приложение не могло занять всё дисковое пространство устройства.

Если вам надо указать, где именно хранится файл AssetBundle, вы можете использовать стандартную WWW загрузку (т.е. просто использовать конструктор вместо LoadFromCacheOrDownload), а затем сохранить загруженные данные на диске, используя API .NET файла. Вы можете сохранить требуемые файлы в папку Application.temporaryCachePath (находится в Library/Caches, которая регулярно “очищается” системой) или в папку Application.persistentDataPath (находится в Documents, которая не очищается системой). Вам следует поставить на эти файлы флажок No Backup при помощи iPhone.SetNoBackupFlag, чтобы не создавались их резервные копии в iCloud.

На заметку: Если вы не поставите флажок No Backup, то ваше приложение может быть отклонено при его подаче в App Store.

Вы можете получить доступ к сохранённым файлам, создав WWW объект к URL в форме file:///pathtoyourapplication/Library/savedassetbundle.assetbundle:-

// C#
string cachedAssetBundle = Application.temporaryCachePath + "/savedassetbundle.assetbundle"; 
System.IO.FileStream cache = new System.IO.FileStream(cachedAssetBundle, System.IO.FileMode.Create);
cache.Write(download.bytes, 0, download.bytes.Length);
cache.Close();

iOS.Device.SetNoBackupFlag(cachedAssetBundle);

Debug.Log("Cache saved: " + cachedAssetBundle);

// JS
private var cachedAssetBundle : String = Application.temporaryCachePath + "/savedassetbundle.assetbundle"; 
var cache = new System.IO.FileStream(cachedAssetBundle, System.IO.FileMode.Create);
cache.Write(download.bytes, 0, download.bytes.Length);
cache.Close();

iOS.Device.SetNoBackupFlag(cachedAssetBundle);

Debug.Log("Cache saved: " + cachedAssetBundle);

На заметку: В папке Documents вы можете протестировать чтение сохранённых файлов, если вы включите file sharing (переключение UIFileSharingEnabled на true в вашем Info.plist позволит вам получить доступ из iTunes к папке Documents). Учтите, что содержимое папки Documents кэшируется в iCloud, так что не используйте эту папку для хранения AssetBundles в итоговой сборке, которая будет подаваться. Для дальнейших деталей, см. File System Basics в документации Apple iOS.

Сборка плагина для iOS
Настройка WWW запросов на iOS