1. 程式人生 > 其它 >Unity3d網路載入方法:DownloadHandlerTexture

Unity3d網路載入方法:DownloadHandlerTexture

技術標籤:Unity3d

A DownloadHandler subclass specialized for downloading images for use as Texture objects.

DownloadHandlerTexture stores received data in a pre-allocated Unity Texture object. It is optimized for downloading images from Web servers, and performs image decompression and decoding on a worker thread.


For use cases where you wish to download an image via HTTP and use it as a Texture within Unity, usage of this class is strongly recommended.

一個專門用於下載影象以用作紋理物件的DownloadHandler子類。

DownloadHandlerTexture將接收到的資料儲存在預先分配的Unity紋理物件中。它針對從Web伺服器下載影象進行了優化,並在工作執行緒上執行影象解壓縮和解碼

對於希望通過HTTP下載影象並將其用作Unity中的紋理的用例,強烈建議使用此類

https://docs.unity3d.com/ScriptReference/Networking.DownloadHandlerTexture-ctor.html

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class Example : MonoBehaviour
{
    IEnumerator Start()
    {
        using (var uwr = new UnityWebRequest("https://website.com/image.jpg", UnityWebRequest.kHttpVerbGET))
        {
            uwr.downloadHandler = new DownloadHandlerTexture();
            yield return uwr.SendWebRequest();
            GetComponent<Renderer>().material.mainTexture = DownloadHandlerTexture.GetContent(uwr);
        }
    }
}

在某種情況下,在網路上下載圖片和音訊的時候,由於網路等原因載入圖片或者音訊會很慢,就需要將圖片或者音訊快取到本地。這樣在讀取本地圖片和音訊會很快。在網上也搜尋了一些方法主要原理就是查詢本地是否有這個檔案,然後決定是去網上下載,還是本地載入。這裡主要用到的方法就是讀寫本地檔案和網上下載檔案。下面是程式碼。

CacheImage.cs

using UnityEngine;
using System.Collections;
using System.IO;
using System;
using UnityEngine.Events;
using UnityEngine.Networking;
 
/// <summary>
/// 圖片快取
/// </summary>
namespace Tools.Cache
{
    public class CacheManager : MonoBehaviour
    {
        private static CacheManager cache = null;
 
        private string cachePath = "";
 
        private static UnityAction<Texture2D> textureCacheEvent;
        private static UnityAction<Sprite> spriteCacheEvent;
        private static UnityAction<AudioClip> clipCacheEvent;
 
        void Awake()
        {
            cachePath = //Application.persistentDataPath;
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
        Application.dataPath + "/StreamingAssets/Cache";
#elif UNITY_IPHONE || UNITY_ANDROID
        Application.persistentDataPath + "/Cache";
#else
        string.Empty;
#endif
        }
        public static CacheManager GetCache()
        {
            if (cache == null)
            {
                GameObject go = new GameObject("CacheManager");
                cache = go.AddComponent<CacheManager>();
            }
            return cache;
        }
 
        public void DownLoad(string url, string identifyId, UnityAction<Texture2D> callback)
        {
            textureCacheEvent = callback;
            StartCoroutine(Load(url, identifyId));
        }
        public void DownLoad(string url, string identifyId, UnityAction<Sprite> callback)
        {
            spriteCacheEvent = callback;
            StartCoroutine(Load(url, identifyId));
        }
        public void DownLoad(string url, string identifyId, UnityAction<AudioClip> callback)
        {
            clipCacheEvent = callback;
            StartCoroutine(Load(url, identifyId));
        }
 
        /// <summary>
        /// 判斷是否本地有快取
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private IEnumerator Load(string url, string identifyId)
        {
            if (!string.IsNullOrEmpty(url))
            {
                string _suffix = url.Split('.')[url.Split('.').Length - 1];
                string _name = "{0}." + _suffix;
                if (!File.Exists(Path.Combine(Path.Combine(cachePath, _suffix), string.Format(_name, identifyId))))
                {
                    //網路上下載
                    yield return DownLoadByUnityWebRequest((new Uri(url)).AbsoluteUri, (data) =>
                     {
                        //儲存至快取路徑
                        if (!Directory.Exists(Path.Combine(cachePath, _suffix)))
                         {
                             Directory.CreateDirectory(Path.Combine(cachePath, _suffix));//建立新路徑
                        }
                         File.WriteAllBytes(Path.Combine(Path.Combine(cachePath, _suffix), string.Format(_name, identifyId)), data);
                     });
                }
                else
                {
                    //已在本地快取  
                    string filePath = "file:///" + Path.Combine(Path.Combine(cachePath, _suffix), string.Format(_name, identifyId));
                    yield return DownLoadByUnityWebRequest(filePath);
                }
            }
        }
        /// <summary>
        /// UnityWebRequest
        /// </summary>
        /// <param name="url"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        private IEnumerator DownLoadByUnityWebRequest(string url, Action<byte[]> callback = null)
        {
            UnityWebRequest uwr = new UnityWebRequest(url);
            if (textureCacheEvent != null)
            {
                DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
                uwr.downloadHandler = downloadTexture;
                yield return uwr.SendWebRequest();
 
                Texture2D texture = null;
                if (!uwr.isNetworkError)
                {
                    texture = downloadTexture.texture;
                }
                textureCacheEvent.Invoke(texture);
            }
            if (spriteCacheEvent != null)
            {
                DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
                uwr.downloadHandler = downloadTexture;
                yield return uwr.SendWebRequest();
 
                Texture2D texture = null;
                if (!uwr.isNetworkError)
                {
                    texture = downloadTexture.texture;
                }
                Sprite sp = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f);
                spriteCacheEvent.Invoke(sp);
            }
            if (clipCacheEvent != null)
            {
                DownloadHandlerAudioClip downloadAudioClip = new DownloadHandlerAudioClip(url, AudioType.WAV);
                uwr.downloadHandler = downloadAudioClip;
                yield return uwr.SendWebRequest();
 
                AudioClip audioClip = null;
                if (!uwr.isNetworkError)
                {
                    audioClip = downloadAudioClip.audioClip;
                }
                clipCacheEvent.Invoke(audioClip);
            }
            if (callback != null)
            {
                callback.Invoke(uwr.downloadHandler.data);
            }
        }
        /// <summary>
        /// WWW
        /// </summary>
        /// <param name="url"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        private IEnumerator DownLoadByWWW(string url, Action<byte[]> callback = null)
        {
            WWW www = new WWW(url);
            yield return www;
            if (textureCacheEvent != null)
            {
                textureCacheEvent.Invoke(www.texture);
            }
            if (spriteCacheEvent != null)
            {
                Sprite sp = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width, www.texture.height), Vector2.one * 0.5f);
                spriteCacheEvent.Invoke(sp);
            }
            if (clipCacheEvent != null)
            {
                clipCacheEvent.Invoke(www.GetAudioClip());
            }
            if (callback != null)
            {
                callback.Invoke(www.bytes);
            }
        }
    }
}

上面的程式碼,不用拖到任何物體上就能使用。只要拖到專案的任意目錄就能直接使用。下面是使用方法。

using UnityEngine;
using Tools.Cache;
 
public class Test : MonoBehaviour
{
    public RawImage image;
    // Use this for initialization
    void Start()
    {
        string url = "https://www.shijunzh.com/wp-content/uploads/2017/06/cropped-icon.png";
        string name = "123";
        CacheImage.GetCache().DownLoad(url, name, CacheEvent);
    }
 
    void CacheEvent(Texture2D t)
    {
        image.texture = t;
    }
}

其中,在DownLoad方法裡第一個引數是圖片的url地址,第二個引數是儲存到本地的圖片名稱。也是用這個名稱去判斷本地有沒有這個圖片的,所以這個引數最好具有唯一性的。第三個引數是一個委託方法,用來接收載入的圖片的。

上面的指令碼改了第三版了,新增了UnityWebRequest網路請求下載方法。也保留了WWW的方法。根據官方最新的測試版,可能要徹底棄用WWW,所以就自行取捨吧。