Its a VN style game with user generated content and I need to load the image without delay.
Due to it being user generated content the images will be siting in a folder with the game. Due to the same reason I cant preload the images, since I cant know which will be the next image to load.
I have tried UnityWebRequest, WWW or File.ReadAllBytes and all have more delay than I expected, even thou Im running it on a SSD.
Is there a faster way?
The code im using for testing the loading time of the images
using UnityEngine;
using System.IO;
using UnityEngine.Networking;
using System.Collections;
using UnityEngine.UI;
using System.Threading.Tasks;
/// <summary>
/// 2020/19/05 -- Unity 2019.3.3f1 -- C#
/// </summary>
public class itemCreatorImageLoad : MonoBehaviour
{
public Image image; // this is referencing to a UI Panel
private Texture2D texture2D;
private UnityWebRequest uwr;
public RawImage rawImage; // this is referencing to a UI rawImage
// path = @"C:\UnityTests\Referencing\Referencing\Assets\StreamingAssets\Items\image.png"
// the @ handles the / and \ conventions that seem to come from the program using paths for the web
// C:/.../.../... web
// C:\...\...\... pc
public void LoadImageWWW(string path)
{
if (texture2D)
{
Destroy(texture2D); // this follows the reference and destroys the texture. Else it would just get a new one and the old textures start piling up in your memory, without you being able to remove them.
}
texture2D = new Texture2D(1, 1);
texture2D = new WWW(path).textureNonReadable as Texture2D;
image.sprite = Sprite.Create(texture2D, new Rect(0.0f, 0.0f, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f), 100.0f);
image.preserveAspect = true;
}
public void LoadImageWWWv2(string path)
{
// "http://url/image.jpg"
StartCoroutine(setImage(path));
}
IEnumerator setImage(string url) // this comes from https://stackoverflow.com/questions/31765518/how-to-load-an-image-from-url-with-unity
{
Texture2D texture = image.canvasRenderer.GetMaterial().mainTexture as Texture2D;
WWW www = new WWW(url);
yield return www;
// calling this function with StartCoroutine solves the problem
Debug.Log("Why on earh is this never called?");
www.LoadImageIntoTexture(texture);
www.Dispose();
www = null;
}
public void LoadImageReadAllBytes(string path)
{
byte[] pngBytes = File.ReadAllBytes(path);
if (texture2D)
{
Destroy(texture2D); // this follows the reference and destroys the texture. Else it would just get a new one and the old textures start piling up in your memory, without you being able to remove them.
}
texture2D = new Texture2D(1, 1);
texture2D.LoadImage(pngBytes);
image.sprite = Sprite.Create(texture2D as Texture2D, new Rect(0.0f, 0.0f, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f), 100.0f);
image.preserveAspect = true;
}
public void LoadImageUnityWebRequest(string path)
{
StartCoroutine(LoadImageCorroutine());
IEnumerator LoadImageCorroutine()
{
using (uwr = UnityWebRequestTexture.GetTexture(@path))
{
yield return uwr.SendWebRequest();
// I would always check for errors first
if (uwr.isHttpError || uwr.isNetworkError)
{
Debug.LogError($"Could not load texture do to {uwr.responseCode} - \"{uwr.error}\"", this);
yield break;
}
// Destroy the current texture instance
if (rawImage.texture)
{
Destroy(texture2D); // this follows the reference and destroys the texture. Else it would just get a new one and the old textures start piling up in your memory, without you being able to remove them.
}
rawImage.texture = DownloadHandlerTexture.GetContent(uwr);
image.sprite = Sprite.Create(rawImage.texture as Texture2D, new Rect(0.0f, 0.0f, rawImage.texture.width, rawImage.texture.height), new Vector2(0.5f, 0.5f), 100.0f);
image.preserveAspect = true;
}
StopCoroutine(LoadImageCorroutine());
}
}
public void LoadImageUnityWebRequestv2(string path)
{
StartCoroutine(LoadImageUnityWebRequestv2Coroutine(path));
}
IEnumerator LoadImageUnityWebRequestv2Coroutine(string MediaUrl) // this comes from https://stackoverflow.com/questions/31765518/how-to-load-an-image-from-url-with-unity
{
UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
Debug.Log(request.error);
}
else
{
rawImage.texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
}
}
// a async version that I grabbed from somewhere, but I dont remember where anymore
[SerializeField] string _imageUrl;
[SerializeField] Material _material;
public async void MyFunction()
{
Texture2D texture = await GetRemoteTexture(_imageUrl);
_material.mainTexture = texture;
}
public static async Task<Texture2D> GetRemoteTexture(string url)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
{
//begin requenst:
var asyncOp = www.SendWebRequest();
//await until it's done:
while (asyncOp.isDone == false)
{
await Task.Delay(1000 / 30);//30 hertz
}
//read results:
if (www.isNetworkError || www.isHttpError)
{
//log error:
#if DEBUG
Debug.Log($"{ www.error }, URL:{ www.url }");
#endif
//nothing to return on error:
return null;
}
else
{
//return valid results:
return DownloadHandlerTexture.GetContent(www);
}
}
}
}