Unity, How to download image from url?

Have you often end up like me, where you got APIs that returns bunch image URLs which you need to download and show in your Unity app or game?

If yes, let's try and make a Utility class which you have to create only once and can be used in all your future projects with similar functionality.

Without any further ado Let's get coding.

First we create a simple class which will handle the operations related to Image textures, Lets call it "TextureUtils.cs" and create a method which we will call everytime we need to download any image from a URL.

public class TextureUtils
{
    /// <summary>
    /// Download texture 2d from given url
    /// </summary>
    /// <param name="url">URL of the image</param>
    /// <param name="monoBehaviour">Mono behaviour on which to run coroutine;/param>
    /// <param name="OnSuccess">Callback which will invoke when image will download successfully</param>
    /// <param name="OnFailure">Callback which will invoke in case of failure</param>
    public static void LoadTextureFromUrl(string url, MonoBehaviour monoBehaviour,
                UnityAction<Texture2D> OnSuccess = null, UnityAction<string> OnFailure = null) {
    }
}

 The method we have just created will be the only method we will ever going to call from outside the class and we have created a static method so we don't even have to reference the class from anywhere.

I have also wrote a summary of what this method is going to do and what would it need as a parameters;

We have a parameter of type string for a URL, then Monobehaviour because we will going to call a coroutine from this method which will run on the provided Monobehaviour.

Then we have 2 optional parameters, rather callbacks to notify result of our method.

Now. lets create a coroutine where we will actually download the image and invoke the callbacks respective of the result of download operation.

private static IEnumerator DownloadTexture(string url, UnityAction<Texture2D> OnSuccess = null,
UnityAction<string> OnFailure = null) {

if (string.IsNullOrEmpty(url)) {
OnFailure?.Invoke("URL is either null or empty");
yield break;
}

UnityWebRequest request = UnityWebRequestTexture.GetTexture(url);
yield return request.SendWebRequest();

if (request.isNetworkError || request.isHttpError) {
OnFailure?.Invoke(request.error);
yield break;
}

Texture2D texture = ((DownloadHandlerTexture) request.downloadHandler).texture;
OnSuccess?.Invoke(texture);
}

Here, we first check if the provided URL is null or empty? If it is then we will invoke our failure callback with the message "URL is either null or empty".

Then we will create a unity web request in order to download the texture, and send the web request.

Then we will check if any error occurs in the operation either a network error or http error? If so we will invoke our failure callback with respective error

Finally, we download texture and store it in our local variable "texture" of type Texture2D and invoke our success callback with downloaded texture.

That's it now we just have to call this coroutine from our previously created method "LoadTextureFromURL()"

Final code of your "TextureUtils.cs" would be like following

using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI
;

public class TextureUtils
{
private static IEnumerator DownloadTexture(string url, UnityAction<Texture2D> OnSuccess = null,
UnityAction<string> OnFailure = null) {

if (string.IsNullOrEmpty(url)) {
OnFailure?.Invoke("URL is either null or empty");
yield break;
}

UnityWebRequest request = UnityWebRequestTexture.GetTexture(url);
yield return request.SendWebRequest();

if (request.isNetworkError || request.isHttpError) {
OnFailure?.Invoke(request.error);
yield break;
}

Texture2D texture = ((DownloadHandlerTexture) request.downloadHandler).texture;
OnSuccess?.Invoke(texture);
}

/// <summary>
/// Download texture 2d from given url
/// </summary>
/// <param name="url">URL of the image</param>
/// <param name="monoBehaviour">Mono behaviour on which to run coroutine</param>
/// <param name="OnSuccess">Callback which will invoke when image will download successfully</param>
/// <param name="OnFailure">Callback which will invoke in case of failure</param>
public static void LoadTextureFromUrl(string url, MonoBehaviour monoBehaviour,
UnityAction<Texture2D> OnSuccess = null, UnityAction<string> OnFailure = null) {
            monoBehaviour.StartCoroutine(DownloadTexture(url, OnSuccess, OnFailure));
}


}

Now let's head over to unity and setup our scene for testing our newly created utility script.

I have setup a simple scene in unity with a camera, canvas, an image, textmesh pro and eventsystem, eventsystem is not necessary in this test case


Now, lets create a script and name it "TextureTest.cs" to handle our downloading operation

using DpgUtils;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class TextureTest : MonoBehaviour {
[SerializeField] private string url = "https://picsum.photos/300/300";
[SerializeField] private Image img;
[SerializeField] private TMP_Text tmpText;

private void Awake() {
TextureUtils.LoadTextureFromUrl(url, this, DownloadSuccessful, DownloadFailed);
}

private void DownloadSuccessful(Texture2D texture2D) {
tmpText.gameObject.SetActive(false);
img.sprite = Sprite.Create(texture2D,
new Rect(0f,0f, texture2D.width, texture2D.height), Vector2.zero);
}

private void DownloadFailed(string message) {
tmpText.text = message;
}
}

Here, We have a string url, reference of our image and text mesh pro text.

Then in awake we are calling our Method from TextureUtils, and we have 2 methods that we will be called respectively based on result of our download operation

In DownloadSuccessful() we are just hiding our text and displaying texture in our image, In DownloadFailed() we are just displaying the failure message

Now lets attach this script onto any GameObject, I have attached it on my MainCamera, then lets drag our references in appropriate slots in inspector

 

Let's hit play and if everything is done correctly the image should get displayed like following:


And that's it. There we have our very own utility script which now can be used in any project. All you have to do is drag and drop it in our project.

Please note that textures loaded in, will remain into memory until scene unloads, so make sure to release the texture memory if you don't need it anymore.

 

Thank you.

Comments