Проблемы с отображением спрайтов, загруженных из AssetBundle в режиме редактора воспроизведения
Я борюсь с проблемой в Unity, загружающей Спрайты из SpriteAtlas, загруженной в AssetBundle.
В нашей текущей игре я пытаюсь реализовать AssetBundles, чтобы убрать использование папки "Ресурсы" и уменьшить накладные расходы памяти (среди прочего).
В приложении Game загруженные спрайты некорректно отображаются при работе в редакторе, поэтому я создал небольшой тестовый проект, чтобы лучше понять проблему. К сожалению, тестовый проект работает отлично, хотя я использую идентичный код для загрузки и отображения спрайтов. Я буду называть эти две версии TestApp и GameApp. Напомню, что эта проблема является проблемой только при работе в редакторе (а не в окончательных сборках устройства), однако для нас это является переломным моментом, поскольку мы просто не можем разрабатывать и тестировать приложение. Обработка получения сборок на устройстве просто слишком долгая по сравнению с запуском в редакторе.
Упрощенная версия скрипта, которую я использую для загрузки пакетов ресурсов, выглядит следующим образом. (Это было значительно упрощено для краткости, включая удаление всего кэширования объектов и обработки ошибок и т. Д.)
public IEnumerator GetSpriteFromBundle(string bundleURL, string spriteAtlasName, string spriteName, Action<Sprite> onLoadAction)
{
// get the AssetBundle
AssetBundle bundle = null;
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);
yield return request.SendWebRequest();
if (!request.isNetworkError && !request.isHttpError)
{
bundle = DownloadHandlerAssetBundle.GetContent(request);
}
// Get the SpriteAtlas
SpriteAtlas atlas = null;
if (bundle != null)
{
if (bundle.Contains(spriteAtlasName))
{
AssetBundleRequest assetRequest = bundle.LoadAssetAsync<SpriteAtlas>(spriteAtlasName);
yield return assetRequest;
if (assetRequest.isDone)
{
atlas = assetRequest.asset as SpriteAtlas;
}
}
}
// Get the Sprite
Sprite sprite = null;
if (atlas != null)
{
sprite = atlas.GetSprite(spriteName);
}
onLoadAction(sprite);
}
Сценарий, который я использую, чтобы вызвать его для загрузки Sprite, выглядит следующим образом (снова обработка ошибок исключается):
public void Start()
{
UnityEngine.UI.Image displayImage = GameObject.Find("Path/To/ImageObject").GetComponent<UnityEngine.UI.Image>();
StartCoroutine(
GetSpriteFromBundle(
"https://mycdn.com/myassetbundles/gamesprites", // AssetBundleURL
"GameSprites", // SpriteAssetName
"Icon1", // SpriteName
(sprite) =>
{
displayImage.sprite = sprite;
})
);
}
Конечным результатом этого является то, что все работает и загружается правильно в TestApp, но при воспроизведении GameApp в редакторе спрайты либо невидимы, либо отображаются в виде странного изображения с 3 квадратами в нем.
Единственное отличие, которое я вижу, состоит в том, что когда я использую отладчик фреймов для просмотра различий между TestApp и GameApp, TestApp показывает текстуру SpriteAtlas в пакете, а GameApp - нет.
Как вы можете видеть здесь в TestApp, текстура установлена правильно.
А вот в GameApp текстура не установлена
Вещи, которые я проверил и подтвердил между версиями
- Ни в GameApp, ни в TestApp нет ошибок или исключений.
- Он работает правильно при сборке и развертывании на устройстве (пока протестировано только на Android)
- Спрайтовый объект возвращается в обратном вызове onLoadAction в GameApp.
- Я использую одинаковые AssetBundles и Sprites в обоих приложениях.
- Я провел параллельное сравнение настроек объекта Image в инспекторе в обоих приложениях.
- Оба приложения настроены на одну и ту же платформу сборки (я пробовал Android, WebGL и StandaloneWindows, и у всех одинаковый результат)
- AssetBundles созданы для правильной платформы сборки (как указано выше)
Единственное различие, которое я вижу между TestApp и GameApp, заключается в том, что GameApp намного больше / сложнее, и в нем происходит смена сцены (мы начинаем со сцены загрузки, прежде чем перейти в игровую сцену), но я не не вижу, как что-либо из этого должно повлиять на что-либо.
Я также настроил и протестировал версию, используя AssetBundle.LoadFromFileAsync() и загрузив файл из папки StreamingAssets, с теми же результатами
Итак, мои вопросы: это ошибка в редакторе Unity? Что я должен смотреть, чтобы попытаться это исправить? Мы не можем использовать AssetBundles, пока я не найду решение.
Я использовал актив AssetBundleBrowser для настройки AssetBundles.
Я тестировал с различными версиями Unity, от более ранних выпусков 2018.1 до последнего выпуска (2018.2.7f1 на момент написания).
(Крест размещен на форумах Unity)
--- Обновить ---
Было упомянуто, что это двойной вопрос в этом вопросе, однако я задаю совершенно другой вопрос. Мой код работает правильно на устройстве, но не работает в редакторе Unity.
Я также попытался реструктурировать свой код для запроса SpriteAtlas, а не SpriteAtlas, и с помощью метода LoadAssetWithSubAssetsAsync со следующим кодом, и у меня все еще остается тот же конечный результат, когда спрайт не отображается в редакторе.
private IEnumerator GetSpriteFromBundle(string bundleURL, string spriteName, Action<Sprite> onLoadAction)
{
// get the AssetBundle
AssetBundle bundle = null;
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);
yield return request.SendWebRequest();
if (!request.isNetworkError && !request.isHttpError)
{
bundle = DownloadHandlerAssetBundle.GetContent(request);
}
// Get the Sprite
Sprite sprite = null;
if (bundle != null)
{
if (bundle.Contains(spriteName))
{
AssetBundleRequest assetRequest = bundle.LoadAssetWithSubAssetsAsync<Sprite>(spriteName);
yield return assetRequest;
if (assetRequest.isDone)
{
for (int i = 0; i < assetRequest.allAssets.Length; i++)
{
sprite = assetRequest.allAssets[i] as Sprite;
if (sprite != null && sprite.name == spriteName)
{
onLoadAction(sprite);
yield break;
}
}
}
}
}
onLoadAction(null);
}
1 ответ
Оказывается, проблема была вызвана настройками SpritePacker.
Если я установил для режима SpritePacker (в меню "Правка-> Настройки проекта-> Редактор") значение "Включено для сборок", то спрайты не будут загружены должным образом, а если для него будет установлено значение "Всегда включено" (по-моему, по умолчанию), то sprites, и SpriteAtlas загружается правильно из AssetBundle.
(Я поднял это как ошибку в Unity, но пока не слышал ответа).