Unity3D:图片音频缓存到本地方法详解

在某种情况下,在网络上下载图片和音频的时候,由于网络等原因加载图片或者音频会很慢,就需要将图片或者音频缓存到本地。这样在读取本地图片和音频会很快。在网上也搜索了一些方法主要原理就是查找本地是否有这个文件,然后决定是去网上下载,还是本地加载。这里主要用到的方法就是读写本地文件和网上下载文件。下面是代码。

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 = "http://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,所以就自行取舍吧。

You May Also Like

About the Author: 大腿Plus

发表评论