David
David

Reputation: 37596

Load and display image from a url

I'm trying to load an image from url to GameObject.

I found the next tutorial:

https://www.youtube.com/watch?v=8UK2EsKBzv8

The download succeeded, but I can't see the image.

What am I doing wrong?

// Use this for initialization
void Start () {
    StartCoroutine(loadSpriteImageFromUrl("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/408px-Google_2015_logo.svg.png"));
}

IEnumerator loadSpriteImageFromUrl(string URL)
{
    // Check internet connection
    if (Application.internetReachability == NetworkReachability.NotReachable)
    {
        yield return null;
    }

    var www = new WWW(URL);
    Debug.Log("Download image on progress");
    yield return www;

    if (string.IsNullOrEmpty(www.text))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        www.LoadImageIntoTexture(texture);                      
        Sprite sprite = Sprite.Create(texture,
            new Rect(0, 0, texture.width, texture.height),      
            Vector2.one / 2);                                     

        GetComponent<SpriteRenderer>().sprite = sprite;    // Change current sprite
    }
}

Before Running After Running

EDIT

After moving as suggested from ScriptRenderer to UI Image, the code looks like this:

IEnumerator loadSpriteImageFromUrl(string URL, GameObject cell)
{
    // Check internet connection
    if(Application.internetReachability == NetworkReachability.NotReachable)
    {
        yield return null;
    }

    var www = new WWW(URL);
    Debug.Log("Download image on progress");
    yield return www;

    if(string.IsNullOrEmpty(www.text))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        www.LoadImageIntoTexture(texture);                      
        Sprite sprite = Sprite.Create(texture, 
            new Rect(0,0, texture.width, texture.height),      
            Vector2.one/2);                                    

        cell.AddComponent<Image>();
        cell.GetComponent<Image>().sprite = sprite;    
    }
}

But I'm getting next result to the screen (and not the image in the url):

enter image description here

Upvotes: 3

Views: 12499

Answers (2)

JoJue
JoJue

Reputation: 1

Thanks Programmer for the detailed answer! I just wanted to add an async version based on Programmer's snippets in case you don't want to work with coroutines

public async Task<Sprite> GetSpriteFromURL(string url)
{
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
    UnityWebRequestAsyncOperation task = www.SendWebRequest();
    
    while (!task.isDone) await Task.Yield();
    if (www.result == UnityWebRequest.Result.ProtocolError || www.result == UnityWebRequest.Result.ConnectionError)
    {
        throw new System.Exception("Error while Receiving: " + www.error);
    }
    else
    {
        Debug.Log("Success");
        Texture2D tex = DownloadHandlerTexture.GetContent(www);
        return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
    }
}

Usage:

public async Task<Sprite> GetImageForX(string example)
{
    if (example == "A") 
        return await GetSpriteFromURL(URL1);
    else 
        return await GetSpriteFromURL(URL2);
}

Upvotes: 0

Programmer
Programmer

Reputation: 125455

Your code is fine. The downloaded Image is not showing because you are in the Scene-View and the camera is away from it.

enter image description here

Select the GameObject the script is attached to then press F. It should zoom into it and you will see the downloaded image. See here for how to reset your Unity layout to get the Game-View back.

enter image description here



If you still can't see the image then the SpriteRenderer is not in front of the camera. From the screenshot, its position is 0,0,0 so make sure that the camera's position is 0,0,-10.

The right Way to Display Image:

To simply display image in Unity, use the Image or RawImage component. RawImage is recommended since it doesn't generate garbage when changing the Texture. You should already know how to di this from th

If you need to attach Rigidbody or 2D Colliders to that Image then use SpriteRenderer or MeshRenderer for 3D Objects to display the image.

These are the four ways to display an image in Unity. #2 is recommended if no physics or collision is needed at-all:

1.With the Image Component:

public Image imageToDisplay;
string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/408px-Google_2015_logo.svg.png";

void Start()
{
    StartCoroutine(loadSpriteImageFromUrl(url));
}

IEnumerator loadSpriteImageFromUrl(string URL)
{

    WWW www = new WWW(URL);
    while (!www.isDone)
    {
        Debug.Log("Download image on progress" + www.progress);
        yield return null;
    }

    if (!string.IsNullOrEmpty(www.error))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        www.LoadImageIntoTexture(texture);

        Sprite sprite = Sprite.Create(texture,
            new Rect(0, 0, texture.width, texture.height), Vector2.zero);

        imageToDisplay.sprite = sprite;
    }
}

There have been problems with LoadImageIntoTexture in the past. For this reason, my other examples won't use LoadImageIntoTexture. If you see a question mark as the Image then use www.bytes with the Texture2D.LoadImage function.

Simply replace:

Texture2D texture = new Texture2D(1, 1);
www.LoadImageIntoTexture(texture);

with

Texture2D texture = new Texture2D(1, 1);
texture.LoadImage(www.bytes);
texture.Apply();

2.With the RawImage Component(Recommended):

public RawImage imageToDisplay;
string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/408px-Google_2015_logo.svg.png";

void Start()
{
    StartCoroutine(loadSpriteImageFromUrl(url));
}

IEnumerator loadSpriteImageFromUrl(string URL)
{

    WWW www = new WWW(URL);
    while (!www.isDone)
    {
        Debug.Log("Download image on progress" + www.progress);
        yield return null;
    }

    if (!string.IsNullOrEmpty(www.error))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        texture.LoadImage(www.bytes);
        texture.Apply();


        imageToDisplay.texture = texture;
    }
}

3.With the SpriteRenderer Component:

Mostly used for 2D Objects and 2D physics simulation with Rigidbody2D and 2D Colliders. If not then use the UI(#1 or #2) above.

public SpriteRenderer imageToDisplay;
string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/408px-Google_2015_logo.svg.png";

void Start()
{
    StartCoroutine(loadSpriteImageFromUrl(url));
}

IEnumerator loadSpriteImageFromUrl(string URL)
{

    WWW www = new WWW(URL);
    while (!www.isDone)
    {
        Debug.Log("Download image on progress" + www.progress);
        yield return null;
    }

    if (!string.IsNullOrEmpty(www.error))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        www.LoadImageIntoTexture(texture);

        Sprite sprite = Sprite.Create(texture,
            new Rect(0, 0, texture.width, texture.height), Vector2.zero);


        imageToDisplay.sprite = sprite;
    }
}

4.With the MeshRenderer Component:

Mostly used for 3D Objects and 3D physics simulation with Rigidbody and 2D Colliders. If not then use the UI(#1 or #2) above. Just a use a Plane, Quad or a Cube with a MeshRenderer.

public MeshRenderer imageToDisplay;
string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/408px-Google_2015_logo.svg.png";

void Start()
{
    StartCoroutine(loadSpriteImageFromUrl(url));
}

IEnumerator loadSpriteImageFromUrl(string URL)
{

    WWW www = new WWW(URL);
    while (!www.isDone)
    {
        Debug.Log("Download image on progress" + www.progress);
        yield return null;
    }

    if (!string.IsNullOrEmpty(www.error))
    {
        Debug.Log("Download failed");
    }
    else
    {
        Debug.Log("Download succes");
        Texture2D texture = new Texture2D(1, 1);
        www.LoadImageIntoTexture(texture);

        imageToDisplay.material.mainTexture = texture;
    }
}

New Unity version:

The WWW API seems to be deprecated now. UnityWebRequest should now be used.

public Image imageToUpdate;

void Start()
{
    StartCoroutine(downloadImage());
}

IEnumerator downloadImage()
{
    string url = "http://wallpaper-gallery.net/images/hq-images-wallpapers/hq-images-wallpapers-12.jpg";

    UnityWebRequest www = UnityWebRequest.Get(url);

    DownloadHandler handle = www.downloadHandler;

    //Send Request and wait
    yield return www.SendWebRequest();

    if (www.isHttpError || www.isNetworkError)
    {
        UnityEngine.Debug.Log("Error while Receiving: " + www.error);
    }
    else
    {
        UnityEngine.Debug.Log("Success");

        //Load Image
        Texture2D texture2d = new Texture2D(8, 8);
        Sprite sprite = null;
        if (texture2d.LoadImage(handle.data))
        {
            sprite = Sprite.Create(texture2d, new Rect(0, 0, texture2d.width, texture2d.height), Vector2.zero);
        }
        if (sprite != null)
        {
            imageToUpdate.sprite = sprite;
        }
    }
}

You can also use the UnityWebRequestTexture.GetTexture and DownloadHandlerTexture.GetContent function to download, process and get the image faster.

IEnumerator downloadImage()
{
    string url = "http://wallpaper-gallery.net/images/hq-images-wallpapers/hq-images-wallpapers-12.jpg";

    UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);

    DownloadHandler handle = www.downloadHandler;

    //Send Request and wait
    yield return www.SendWebRequest();

    if (www.isHttpError || www.isNetworkError)
    {
        UnityEngine.Debug.Log("Error while Receiving: " + www.error);
    }
    else
    {
        UnityEngine.Debug.Log("Success");

        //Load Image
        Texture2D texture2d = DownloadHandlerTexture.GetContent(www);

        Sprite sprite = null;
        sprite = Sprite.Create(texture2d, new Rect(0, 0, texture2d.width, texture2d.height), Vector2.zero);

        if (sprite != null)
        {
            imageToUpdate.sprite = sprite;
        }
    }
}

Upvotes: 8

Related Questions