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,所以就自行取捨吧。