3

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);
        }
    }
}

}

mllhild
  • 67
  • 7
  • System.Threading.Tasks - https://support.unity.com/hc/en-us/articles/208707516-Why-should-I-use-Threads-instead-of-Coroutines- – George Jun 04 '21 at 15:43

0 Answers0