Unity中使用UnityWebRequest进行网络和本地图片加载

在实际项目中,往往会有一些需求是要从网络上加载图片展示出来。例如玩家的头像,公告大图和一些需要加载的展示的图片,这时就需要用代码实现从网络上加载必要的图片资源。

更新迭代版本的Unity已经在逐步放弃对WWW的支持,推出UnityWebRequest,详见Unity资源存放与加载-本地资源 更新资源

UnityWebRequest同时也支持AssetsBundle,xml等文件资源的下载。

本文在基于UnityWebRequest的基础上,实现网络图片和本地磁盘图片的加载,并且实现在屏幕上。

先看看使用WWW是怎么完成图片加载的:

using (WWW www = new WWW(url))
{
    yield return www;
    if (string.IsNullOrEmpty(www.error))
    {
         //获取到链接中的图片
         Texture2D texture = www.texture;
    }
}

这段代码比较简单,返回的www.texture就是链接图片,这样就完成了简单的图片加载了。

但是,实际上,通常需要将图片加载内存和缓存到本地,以便在下一次可以很快的加载,而不用再次从网络上拉取。

流程:                                                                                   

关键代码:github地址

///LoadImageMgr.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using UnityEngine.Networking;


public class LoadImageMgr
{
    /// <summary>
    /// download from web or hard disk
    /// </summary>
    /// <param name="url"></param>
    /// <param name="loadEnd">callback</param>
    /// <returns></returns>
    public IEnumerator LoadImage(string url, Action<Texture2D> loadEnd)
    {
        Texture2D texture = null;
        //先从内存加载
        if (imageDic.TryGetValue(url,out texture))
        {
            loadEnd.Invoke(texture);
            yield break;
        }
        string savePath = GetLocalPath();
        string filePath = string.Format("file://{0}/{1}.png", savePath, UnityUtil.MD5Encrypt(url));
        //from hard disk
        bool hasLoad = false;
        if (Directory.Exists(filePath))
            yield return DownloadImage(filePath, (state, localTexture) =>
            { 
                hasLoad = state;
                if (state)
                {
                    loadEnd.Invoke(localTexture);
                    if (!imageDic.ContainsKey(url))
                        imageDic.Add(url, localTexture);
                }
            });
        if (hasLoad) yield break; //loaded
        //from web
        yield return DownloadImage(url, (state, downloadTexture) =>
        {
            hasLoad = state;
            if (state)
            {
                loadEnd.Invoke(downloadTexture);
                if (!imageDic.ContainsKey(url))
                    imageDic.Add(url, downloadTexture);
                Save2LocalPath(url, downloadTexture);
            }
        });
    }
    public IEnumerator DownloadImage(string url, Action<bool, Texture2D> downloadEnd)
    {
        using (UnityWebRequest request = new UnityWebRequest(url))
        {
            DownloadHandlerTexture downloadHandlerTexture = new DownloadHandlerTexture(true);
            request.downloadHandler = downloadHandlerTexture;
            yield return request.Send();
            if (string.IsNullOrEmpty(request.error))
            {
                Texture2D localTexture = downloadHandlerTexture.texture;
                downloadEnd.Invoke(true, localTexture);
            }
            else
            {
                downloadEnd.Invoke(false, null);
                Debug.Log(request.error);
            }
        }
    }
    /// <summary>
    /// save the picture
    /// </summary>
    /// <param name="url"></param>
    /// <param name="texture"></param>
    private void Save2LocalPath(string url, Texture2D texture)
    {
        byte[] bytes = texture.EncodeToPNG();
        string savePath = GetLocalPath();
        try
        {
            File.WriteAllBytes( string.Format("{0}/{1}.png", savePath , UnityUtil.MD5Encrypt(url)), bytes);
        }
        catch(Exception ex)
        {
            Debug.LogError(ex.ToString());
        }
    }
    /// <summary>
    /// get which path will save
    /// </summary>
    /// <returns></returns>
    private string GetLocalPath()
    {
        string savePath = Application.persistentDataPath + "/pics";
#if UNITY_EDITOR
        savePath = Application.dataPath + "/pics";
#endif
        if (!Directory.Exists(savePath))
        {
            Directory.CreateDirectory(savePath);
        }
        return savePath;
    }
    private Dictionary<string, Texture2D> imageDic = new Dictionary<string, Texture2D>();
    public static LoadImageMgr instance { get; private set; } = new LoadImageMgr();
}
///LoadImageHelper.cs
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class LoadImageHelper : MonoBehaviour
{
    string defaultUrl = "http://avatar.csdnimg.cn/1/E/6/2_u013012420.jpg";
    /// <summary>
    /// use this to load image
    /// </summary>
    /// <param name="texture"></param>
    /// <param name="url"></param>
    public void LoadImage(RawImage rawImage, string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            url = defaultUrl;
        }
        StartCoroutine(LoadTeture(url, (tex) => {
            rawImage.texture = tex;
        }));
    }

    IEnumerator LoadTeture(string url, Action<Texture2D> cb)
    {
        yield return LoadImageMgr.instance.LoadImage(url, cb);
    }
}

猜你喜欢

转载自blog.csdn.net/u013012420/article/details/102681188