Легко загружайте изображения из внутреннего хранилища в unity Android?

#c# #android #performance #unity3d

Вопрос:

Я работал над игрой-головоломкой для устройства Android с использованием игрового движка Unity, и у меня возникли проблемы с загрузкой изображений из внутреннего хранилища. В игре около 400-500 уровней. Которые загружаются во время выполнения в соответствии с требованиями и хранятся во внутреннем хранилище. Проблема возникает при загрузке этих изображений. Загрузка изображений из внутреннего хранилища обходится очень дорого. Функция, отвечающая за загрузку или загрузку изображения, приведена ниже,

 public IEnumerator DownloadOrLoadImage(string link, string dirName, int index = -1) {  if (!loadFromResources)  {  //Extract Link  int startPos = link.LastIndexOf("https://drive.google.com/file/d/")   "https://drive.google.com/file/d/".Length;  int length = link.IndexOf("/view?usp=sharing") - startPos;  if (length gt;= 1)  {  string ID = link.Substring(startPos, length);   link = "https://drive.google.com/uc?export=downloadamp;id="   ID;   if (File.Exists(Application.persistentDataPath   "/.cache/"   ID))  {  if (index != -1 amp;amp; index == LevelMenuLoader.instance.totalJsonCount)  {  LevelMenuLoader.instance.AfterMenuDownloadSequence();  }  print("Loading from the device");   UnityWebRequest request = UnityWebRequestTexture.GetTexture("file://"   Application.persistentDataPath   "/.cache/"   ID);  yield return request.SendWebRequest();   if (request.result != UnityWebRequest.Result.Success)  {  Debug.Log(request.error);  }  else  {  byte[] bytes = ((DownloadHandlerTexture)request.downloadHandler).data;   if (bytes.Length gt; 1)  this.GetComponentlt;RawImagegt;().texture = ((DownloadHandlerTexture)request.downloadHandler).texture;  }   request.downloadHandler.Dispose();  request.Dispose();  isImageDownloaded = true;  }  else  {  LevelMenuLoader.instance.AfterMenuDownloadSequence();  print("Downloading from the web");    using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(link))  {  yield return request.SendWebRequest();   if (request.isNetworkError || request.isHttpError)  Debug.Log(request.error);  else  {  this.GetComponentlt;RawImagegt;().texture = ((DownloadHandlerTexture)request.downloadHandler).texture;   byte[] bytes = ((DownloadHandlerTexture)request.downloadHandler).data;  if (bytes.Length gt; 1)  {  File.WriteAllBytes(Application.persistentDataPath   "/.cache/"   ID, bytes);  isImageDownloaded = true;  }   request.downloadHandler.Dispose();  request.Dispose();  }  }  }  }  }  else  {  // Debug.Log("Loaded from resources");  this.GetComponentlt;RawImagegt;().texture = Resources.Loadlt;Texturegt;("Levels/"   dirName   "/"   this.GetComponentlt;LevelInformationgt;().m_LevelID);  }  

Мне жаль, что это так долго, но это просто проверка, существует ли файл, загрузите изображение из хранилища или загрузите его. Я обнаружил, что на данный момент это наиболее эффективно и с наименьшей задержкой. Когда дело доходит до загрузки более 300 изображений, это серьезная головная боль, и загрузка изображений занимает до 3-4 секунд, а на некоторых устройствах она вообще не загружается из-за некоторых ограничений использования памяти на некоторых устройствах. Это действительно поможет, если кто-нибудь сможет помочь или помочь мне оптимизировать код таким образом, чтобы он был очень простым и быстрее загружал изображения.

PS: Я пробовал объединять объекты для просмотра прокрутки, поэтому я загружаю только те изображения, которые необходимы, и удаляю их, когда они не видны на экране. Но это непрактично, так как загрузка изображения создает небольшую задержку и происходит не так быстро, как нужно. Любое предложение будет отличным.

Я прошу прощения, если я нарушаю какие-либо правила или мое форматирование не подходит. Пожалуйста, дайте мне знать, чтобы я мог это исправить.

Спасибо.

Комментарии:

1. Вам придется либо пожертвовать временем загрузки, либо памятью. Кроме того, вы пробовали создавать миниатюры меньшего размера (при загрузке на устройство или с сервера или создании на лету, хотя я подозреваю, что это нецелесообразно, так как у вас уже есть проблема со временем загрузки) для экранов, на которых вместо этого просматривается много изображений?

2. Привет, @LukeVo Спасибо за ответ. Я не возражаю против времени загрузки, но загрузка более 400 изображений в память создает много проблем (это не так много памяти), но некоторые устройства имеют ограничения на внезапный всплеск использования памяти, которые мешают игре загружать изображения. Это очень заметно на устройствах Samsung и IOS. Из-за этого игра не будет загружаться после загрузки. Миниатюры довольно маленькие, размером 512×512, около 100 кб каждая. Это самое маленькое, что я могу сделать для миниатюры, я думаю. Эти проблемы с загрузкой изображений относятся только к меню, в котором требуется более 400 изображений в режиме прокрутки.

3. Раньше я разрабатывал игры, не уверен, что сейчас все по-другому, но файл изображения объемом 100 КБ не имеет такого же объема в памяти. В памяти это всегда растровое изображение (т. е. 3 или 4 байта на пиксель). 512×512 довольно большой! Я помню, что тогда (10 лет назад) мы могли загрузить только текстуру 2048×2048 и сжать все в этом пределе.

4. Я понимаю. Есть ли какое-либо обходное решение для этого? потому что снижение ниже 512×512, я полагаю, приведет к очень плохому качеству. Мы максимально оптимизировали изображения, чтобы сохранить качество при меньшем размере.

5. Зачем вам нужно загружать все 300 изображений? Пользователи не могут просматривать их все сразу. Допустим, я предполагаю, что у вас есть экран меню, чтобы пользователь мог выбрать уровень, и экран, на котором действительно нужно большое хорошее изображение для игры. Экран меню, вы загружаете, скажем, 30 миниатюр размером 50х50, например, что было бы очень быстро и потребляло бы не так много памяти. Затем на экран воспроизведения вы фактически загружаете файлы 512×512.

Ответ №1:

может быть, это решение

предварительно загрузите их в начале, а затем покажите игроку.Этот метод в основном используется для компьютерных игр, таких как Battlefield. Например, частицы и оружие загружаются в начале, и когда они вам понадобятся, они не будут появляться вместе с вами, а телепортируются к вам для лучшей производительности. В вашем случае это должно быть отличным решением, чтобы просто загрузить все изображения заранее, таким образом, все будет работать гладко (до тех пор, пока вы не встроили необоснованные журналы отладки или другие ненужные процессы вычисления).

Комментарии:

1. Привет @somewhat32, спасибо за решение. Это то, что я делаю прямо сейчас, чтобы избежать дальнейшей загрузки. И для меня это работает как заклинание в редакторе unity. Но некоторые мобильные устройства имеют какие-то ограничения. Они не позволяют приложениям и играм мгновенно использовать оперативную память. Особенно в Samsung и IOS. Это странное поведение, на некоторых устройствах игра работает как заклинание, но загрузка занимает так много времени, а на некоторых она просто не проходит мимо экрана загрузки. В Google Play есть игра под названием Art puzzle, в которой есть та же механика, что и у меня, но они делают это безупречно.

2. ах, я вижу, как ты создаешь художественную головоломку, и я думал, что ты создаешь свою собственную галерею на основе Google диска. В любом случае, я думаю, что они помещают изображения в файлы игры, как будто они публикуют их со всеми изображениями сразу. если вы уменьшите разрешение, вам сойдет с рук около 300 уровней, вы используете около 900 Мб для изображений, но вы можете переработать изображения, если у вас будет такая возможность. Но даже гигабайт-это не так много для отличной игры. Если вы не можете найти способ решить проблему с оперативной памятью, я рекомендую опубликовать вашу игру со всеми этими реализованными изображениями, без внешних источников.

3. Преимуществом является то, что игроку не нужно подключаться к Интернету.

4. Привет, Да, у нас почти одинаковая концепция, с той лишь разницей, что наша игра-головоломка. Они не поместили все изображения в файлы игры. Их размер загрузки очень лаконичен-около 50 мегабайт или около того. Они загружают их в режиме реального времени, так как у них самих более 500 уровней (то есть около 1500 изображений). Причина, по которой мы решили выполнить загрузку в режиме реального времени, заключается в том, чтобы сэкономить размер загрузки для игроков из play Store, и им не нужно ждать завершения загрузки.

5. Мы закодировали игру таким образом, что игрокам не нужно ничего ждать, чтобы закончить. У нас есть ванильные 10 уровней в игре, прежде чем они закончат эти 10 уровней, там должны быть другие активы в порядке. Они могут начать играть мгновенно, и игра будет управлять всеми загрузками в фоновом режиме. В игру также можно играть в автономном режиме.