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