Проблемы с отображением спрайтов, загруженных из 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, текстура установлена ​​правильно. TestApp - текстура правильно установлена

А вот в GameApp текстура не установлена 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, но пока не слышал ответа).

Другие вопросы по тегам