如何在Unity中从URL加载图像?

20

请救救我,不然我就要疯了。

无论我搜索多少次,我总是得到以下(通常已停止支持的)代码版本:

IEnumerator setImage(string url) {
    Texture2D texture = profileImage.canvasRenderer.GetMaterial().mainTexture as Texture2D;

    WWW www = new WWW(url);
    yield return www;

    Debug.Log("Why on earh is this never called?");

    www.LoadImageIntoTexture(texture);
    www.Dispose();
    www = null;
}

我使用的是Unity 5而不是4。我正在尝试加载的URL存在。 请给我一些提示。

如何通过HTTP加载图像并在UnityEngine.UI.Image中显示它?


1
你是如何调用 setImage() 方法的?你有什么代码想分享吗? - Umair M
相当平凡... setImage(url); 其中 url 是指向 JPEG 或 PNG 的 URL。 - Michel Jung
6个回答

45

如果使用Unity 2018或更高版本,请使用UnityWebRequest代替WWW类。

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

IEnumerator DownloadImage(string MediaUrl)
{   
    UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
    yield return request.SendWebRequest();
    if(request.isNetworkError || request.isHttpError) 
        Debug.Log(request.error);
    else
        YourRawImage.texture = ((DownloadHandlerTexture) request.downloadHandler).texture;
} 

23

您可以使用async/await来实现:

using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

public static async Task<Texture2D> GetRemoteTexture ( string url )
{
    using( UnityWebRequest www = UnityWebRequestTexture.GetTexture(url) )
    {
        // begin request:
        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 )
        // if( www.result!=UnityWebRequest.Result.Success )// for Unity >= 2020.1
        {
            // 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);
        }
    }
}

使用示例:

[SerializeField] string _imageUrl;
[SerializeField] Material _material;
Texture2D _texture;

async void Start ()
{
    _texture = await GetRemoteTexture(_imageUrl);
    _material.mainTexture = _texture;
}

void OnDestroy () => Dispose();
public void Dispose () => Object.Destroy(_texture);// memory released, leak otherwise

这是一个很酷的方法。我们能用它从本地磁盘加载图片吗? - Filip
@karsnen 是的。使用有效的文件 URI。 - Andrew Łukasik
4
如果你想摆脱 Monobehaviours,强烈推荐异步操作。 - Premier Bromanov

11

简单解释:

https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
public void yourMethod()
{
   StartCoroutine(setImage("http://url/image.jpg")); //balanced parens CAS
}

IEnumerator setImage(string url) {
    Texture2D texture = profileImage.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;
}

8
现在WWW已经过时了,推荐使用UnityWebRequestTexture - Serg

6

在画布中我们不能直接将纹理材质应用于图像组件。因此,我们需要从运行时下载的纹理创建一个精灵,然后在图片组件中应用该精灵。

尝试这个方法:

IEnumerator DownloadImage(string MediaUrl)
    {   
        UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
        yield return request.SendWebRequest();
        if(request.isNetworkError || request.isHttpError) 
            Debug.Log(request.error);
        else{
            // ImageComponent.texture = ((DownloadHandlerTexture) request.downloadHandler).texture;

            Texture2D tex = ((DownloadHandlerTexture) request.downloadHandler).texture;
            Sprite sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(tex.width / 2, tex.height / 2));
            ImageComponent.GetComponent<Image>().overrideSprite = sprite;
        }
    } 

1
感谢Umair M提出的问题,我发现这个方法需要使用Unity的StartCoroutine进行调用。

0
public void OnStart()
{
    StartCoroutine(setImage("http://drive.google.com/myimage.jpg")); 
}

IEnumerator setImage(string url) 
{
    Texture2D texture = null;
    WWW www = new WWW(url);
    yield return www;

    Debug.Log("Why on earth is this never called?");
    texture = www.texture;
    //end show Image in texture 2D
}

WWW类已被弃用,不应再使用。请改用UnityWebRequest。 - Alireza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接