Игра у меня по современным меркам не очень большая (60 Мб).
Я предполагаю "засунуть" в AssetBundle всю свою игру.
Игра состоит из одной одной рабочей сцены, в которой каждый раз при старте очередного мини-гейма динамически генерируется уровень с новой игровой комнатой.
Сейчас я опробовала стандартный подход, когда после первоночальной загрузки игры на устройство на экране появляется сцена-заставка с логотипом игры.
Пока заставка "висит" на экране, я загружаю AssetBundle c основной сценой при помощи простого кода (см. ниже).
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class MainScene : MonoBehaviour
{
public string BundleName = "gameloadscene";
public string SceneName = "LoadScene";
public string ManifestName = "Data";
AssetBundleManifest manifest;
string assetBundlePath = "https://mywebhostingsite.com/assetbundledata/";
IEnumerator Start()
{
// Загрузка данных из PlayerPrefs
Hash128 AssetBundleHashFromCache = Hash128.Parse(PlayerPrefs.GetString("AssetBundleHash", string.Empty));
// Установка флага проверки доступности на возможность осуществления загрузки
bool IsAssetBundleReachableToDownload = false;
// Удаленное чтение значения манифеста для используемого AssetBundle
using (WWW www = new WWW(assetBundlePath + ManifestName))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
// Загрузка невозможна (нет удаленного соединения)
IsAssetBundleReachableToDownload = false;
yield break;
}
// Успешная загрузка значения манифеста для используемого AssetBundle
manifest = www.assetBundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
// Загрузка по удаленному соединению возможна
IsAssetBundleReachableToDownload = true;
yield return null;
www.assetBundle.Unload(false);
} // using()
// Значение хеш-суммы из используемого AssetBundle
Hash128 AssetBundleHashFromAssetBundle;
// Установка флага необходимости загрузки бандла по удаленному соединению
bool IsAssetBundleDownloadNeed = true;
// Проверка доступности удаленного соединения
if (IsAssetBundleReachableToDownload)
{
// Получение значения хеш-суммы для удаленного AssetBundle
AssetBundleHashFromAssetBundle = manifest.GetAssetBundleHash(BundleName);
// Проверка совпадения хеш-сумм для бандла из хеша и из удаленного хостинга
if (AssetBundleHashFromCache.ToString() == AssetBundleHashFromAssetBundle.ToString())
{
IsAssetBundleDownloadNeed = false; // Загрузка удаленного бандла не нужна
}
else
{
IsAssetBundleDownloadNeed = true; // Загрузка удаленного бандла нужна
}
}
else
{
// Сообщение в случае невозможности "достучаться" по сети до удаленного бандла
Debug.Log("IsAssetBundleReachableToDownload: " + IsAssetBundleReachableToDownload.ToString());
}
// Проверка на необходимость загрузки с удаленного хостинга при наличии возможности "достучаться" до удаленного хостинга
if (IsAssetBundleDownloadNeed && IsAssetBundleReachableToDownload)
{
// Получение значения хеш-суммы для удаленного AssetBundle
AssetBundleHashFromAssetBundle = manifest.GetAssetBundleHash(BundleName);
// Загрузка AssetBundle из удаленного хостинга
using (WWW www = WWW.LoadFromCacheOrDownload(assetBundlePath + BundleName, AssetBundleHashFromAssetBundle))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
// Загрузка сцены из полученного AssetBundle
Application.LoadLevel(SceneName);
yield return null;
www.assetBundle.Unload(false);
} // using()
// Сохранение хеш-суммы из AssetBundle
PlayerPrefs.SetString("AssetBundleHash", AssetBundleHashFromAssetBundle.ToString());
PlayerPrefs.Save();
}
else
{
if (!IsAssetBundleDownloadNeed)
{
// Загрузка AssetBundle из локального кеша
using (WWW www = WWW.LoadFromCacheOrDownload(assetBundlePath + BundleName, AssetBundleHashFromCache))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
// Загрузка сцены из полученного AssetBundle
Application.LoadLevel(SceneName);
yield return null;
www.assetBundle.Unload(false);
} // using()
}
}
}// Start()
}
using System.Collections;
public class MainScene : MonoBehaviour
{
public string BundleName = "gameloadscene";
public string SceneName = "LoadScene";
public string ManifestName = "Data";
AssetBundleManifest manifest;
string assetBundlePath = "https://mywebhostingsite.com/assetbundledata/";
IEnumerator Start()
{
// Загрузка данных из PlayerPrefs
Hash128 AssetBundleHashFromCache = Hash128.Parse(PlayerPrefs.GetString("AssetBundleHash", string.Empty));
// Установка флага проверки доступности на возможность осуществления загрузки
bool IsAssetBundleReachableToDownload = false;
// Удаленное чтение значения манифеста для используемого AssetBundle
using (WWW www = new WWW(assetBundlePath + ManifestName))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
// Загрузка невозможна (нет удаленного соединения)
IsAssetBundleReachableToDownload = false;
yield break;
}
// Успешная загрузка значения манифеста для используемого AssetBundle
manifest = www.assetBundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
// Загрузка по удаленному соединению возможна
IsAssetBundleReachableToDownload = true;
yield return null;
www.assetBundle.Unload(false);
} // using()
// Значение хеш-суммы из используемого AssetBundle
Hash128 AssetBundleHashFromAssetBundle;
// Установка флага необходимости загрузки бандла по удаленному соединению
bool IsAssetBundleDownloadNeed = true;
// Проверка доступности удаленного соединения
if (IsAssetBundleReachableToDownload)
{
// Получение значения хеш-суммы для удаленного AssetBundle
AssetBundleHashFromAssetBundle = manifest.GetAssetBundleHash(BundleName);
// Проверка совпадения хеш-сумм для бандла из хеша и из удаленного хостинга
if (AssetBundleHashFromCache.ToString() == AssetBundleHashFromAssetBundle.ToString())
{
IsAssetBundleDownloadNeed = false; // Загрузка удаленного бандла не нужна
}
else
{
IsAssetBundleDownloadNeed = true; // Загрузка удаленного бандла нужна
}
}
else
{
// Сообщение в случае невозможности "достучаться" по сети до удаленного бандла
Debug.Log("IsAssetBundleReachableToDownload: " + IsAssetBundleReachableToDownload.ToString());
}
// Проверка на необходимость загрузки с удаленного хостинга при наличии возможности "достучаться" до удаленного хостинга
if (IsAssetBundleDownloadNeed && IsAssetBundleReachableToDownload)
{
// Получение значения хеш-суммы для удаленного AssetBundle
AssetBundleHashFromAssetBundle = manifest.GetAssetBundleHash(BundleName);
// Загрузка AssetBundle из удаленного хостинга
using (WWW www = WWW.LoadFromCacheOrDownload(assetBundlePath + BundleName, AssetBundleHashFromAssetBundle))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
// Загрузка сцены из полученного AssetBundle
Application.LoadLevel(SceneName);
yield return null;
www.assetBundle.Unload(false);
} // using()
// Сохранение хеш-суммы из AssetBundle
PlayerPrefs.SetString("AssetBundleHash", AssetBundleHashFromAssetBundle.ToString());
PlayerPrefs.Save();
}
else
{
if (!IsAssetBundleDownloadNeed)
{
// Загрузка AssetBundle из локального кеша
using (WWW www = WWW.LoadFromCacheOrDownload(assetBundlePath + BundleName, AssetBundleHashFromCache))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
// Загрузка сцены из полученного AssetBundle
Application.LoadLevel(SceneName);
yield return null;
www.assetBundle.Unload(false);
} // using()
}
}
}// Start()
}
Собираю бандл под Android, заливаю папку c бандлом на хостинг.
Все работает хорошо - бандл с основной сценой исправно подгружается, пока на экране висит сцена с логотипом игры.
В коде автоматически проверяется хеш-сумма бандла, и новый бандл подгружается в случае необходимости.
При тестировании работы с этим бандлом я заметила, что бандл подгружается каждый раз заново, несмотря на то, что он уже был загружен в предыдущий раз при старте игры.
Я использую метод LoadFromCacheOrDownload(), сохраняю в PlayerPrefs значение хеш-суммы загруженного бандла.
При последующей загрузке игры сверяю значения хеш-сумм на удаленном хостинге и в кеше на мобильном устройстве.
Если хеш-суммы не совпадают, провожу повторную загрузку бандла с хостинга на удаленном сервере.
По идее, этот метод должен "подгружать" уже имеющийся AssetBundle с моей основной игровой сценой из кеша на устройстве, если хеш-суммы бандлов на хостинге и устройстве совпадают.
Но этого почему-то не происходит - бандл из кеша c устройства не подгружается.
Я проверила это очень просто - отключив WiFi-сеть на мобильном устройстве.
В протоколе Logcat выводится сообщение "404: Not found".
Основная сцена при этом из кеша почему-то не подгружается, хотя обработка соответствующей ситуации реализована в программном коде.
Сцена с заставкой в запущенном приложении продолжает висеть на экране, ожидая подгрузки бандла из сети.
Скажите, почему не происходит загрузка бандла из кеша в случае использования моего кода?
Каким образом нужно модифицировать программный код, чтобы в случае совпадения хэша бандлов на сервере и на устройстве, сцена все-таки подгружалась из кеша c устройства?
Почему при отсутствии соединения с сервером при запуске игры, который я имитирую удалением папки с бандлом на сервере, не подгружается уже имеющийся бандл со сценой из кеша с устройства?
Опции isCacheEnabled = true,
Application.persistentDataPath = "/data/data/com.comp.assetbundle/files",
Application.temporaryCachePath = "/data/data/com.comp.assetbundle/cache".
Странно, но в этих папках нет ничего похожего на содержимое моей папки https://mywebhostingsite.com/assetbundledata/, которая содержит 4 файла со сгенерированном бандлом:
- Data
- Data.manifest
- gameloadscene
- gameloadscene.manifest
На мобильном устройстве нашла какие-то файлы в папке data/data/com.comp.assetbundle/files/UnityCache/Shared/03eb33c2e54214e09a3458ed89b17bea150e468c6
- __info
- __lock
- BuildPlayer-LoadScene
- BuildPlayer-LoadScene.sharedAssets
LoadScene - это как раз сцена, которую я подгружаю из бандла в проект, но в в Unity этот бандл со сценой у меня называется gameloadscene.
Где вообще должны храниться на Android-устройствах подгружаемые бандлы?
Сохраняют ли они свое изначальное имя или меняют его на BuildPlayer-LoadScene.sharedAssets?
В файл с настройками "/data/data/com.comp.assetbundle/shared_prefs/com.comp.assetbundle.xml" значения хеша из PlayerPrefs после удачного первоначального запуска приложения на устройстве так почему-то и не записались.
Помогите, пожалуйста, разобраться в чем тут загвоздка!
Спасибо за помощь в решении это задачи.