Reputation: 115
I have been working on a puzzle game for the android device using Unity Game Engine, and I have been facing issues with loading the images from internal storage. The game has like 400-500 levels. Which are downloaded at runtime as per demand, and stored in the internal storage. The problem occurs in loading these images. Loading images from internal storage is very expensive. The function that is responsible for downloading or loading image is below,
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 >= 1)
{
string ID = link.Substring(startPos, length);
link = "https://drive.google.com/uc?export=download&id=" + ID;
if (File.Exists(Application.persistentDataPath + "/.cache/" + ID))
{
if (index != -1 && 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 > 1)
this.GetComponent<RawImage>().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.GetComponent<RawImage>().texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
byte[] bytes = ((DownloadHandlerTexture)request.downloadHandler).data;
if (bytes.Length > 1)
{
File.WriteAllBytes(Application.persistentDataPath + "/.cache/" + ID, bytes);
isImageDownloaded = true;
}
request.downloadHandler.Dispose();
request.Dispose();
}
}
}
}
}
else
{
// Debug.Log("Loaded from resources");
this.GetComponent<RawImage>().texture = Resources.Load<Texture>("Levels/" + dirName + "/" + this.GetComponent<LevelInformation>().m_LevelID);
}
I am sorry for it to be so long, but it's simply doing a check, if the file exists, load the image from storage or else download it. I found this to be the most efficient so far and with the least amount of lag. When it comes to loading 300+ images, it's seriously a headache and it takes up to 3-4 seconds to load the images, and in some devices, it won't load at all because of some memory usage limitations in some devices. It will really help if someone can help or guide me to optimize the code in a way that is very seamless and faster to load images.
PS: I have tried object pooling for scroll view, so I only load the images that are needed and dispose of them when they are not visible on the screen. But it's impractical as loading the image creates a bit of lag and it's not as fast as needed. Any suggestion will be great.
I am sorry if I am violating any guidelines or my formatting is not good. Please let me know so I can correct it.
Thank you.
Upvotes: 1
Views: 1854
Reputation: 58
preload them at the beginning and then show them the player This method is mainly used for computational games like Battlefield. For example, the particles and weapons are loaded at the beginning and when you need them they will not spawn with you but teleport to you for better performance. In your case, it should be a great solution to simply load all the images beforehand, that way it will run smoothly (as long as you haven't built in unreasonable debug logs or other unnecessary calculation processes)
Upvotes: 0