Unirx 缓存或下载资源

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17813937/article/details/82802241

扩展一下Unirx下载纹理~

由于公司是使用版本号验证,所以下载的时候提供需要版本号检查本地是否已经缓存该版本

如果版本号不对,重新从服务器下载

使用方式

using UnityEngine;
using UnityEngine.UI;
using UniRx;
using System;

public static class RawImageExtend  {

    public static IDisposable Show(this RawImage target, string url)
    {
        return ObservableWWW.GetTexture2D(url).Subscribe(t => {
            target.texture = t;
        });
    }

    public static IDisposable Show(this RawImage target, string url, int version)
    {
        return ObservableWWW.GetTexture2D(url, version).Subscribe(t => {
            target.texture = t;
        });
    }

    public static IDisposable Show(this RawImage target, Transform parent, string url, int version)
    {
        return target.Show((parent as RectTransform).sizeDelta, url, version);
    }

    public static IDisposable Show(this RawImage target, RectTransform parent, string url, int version)
    {
        return target.Show(parent.sizeDelta, url, version);
    }

    public static IDisposable Show(this RawImage target, Vector2 size, string url, int version)
    {
        return ObservableWWW.GetTexture2D(url, version).Subscribe(t => {
            target.texture = t;
            target.rectTransform.sizeDelta = Tools.ScaleScaling(size, t.width, t.height);
        });
    }
}

扩展

using System;
using System.Collections;
using UnityEngine;
using System.IO;
using System.Text.RegularExpressions;

#if !UniRxLibrary
using ObservableUnity = UniRx.Observable;
#endif

namespace UniRx
{
    using Hash = System.Collections.Generic.Dictionary<string, string>;

    public static partial class ObservableWWW
    {
        static readonly string Http = "http";
        static readonly string Path1 = "{0}/Data/{1}";
        static readonly string Path2 = "/Assets";
        static readonly string Path3 = "{0}/{1}";
        static readonly string UrlRegex = "(http|https)://[a-z.:0-9]+/";
        static readonly string GetSavePathFormat = "{0}/{1}@{2}";
        static readonly char Aite = '@';
        static readonly string GetFilesFormat = "*{0}";

        public static IObservable<Texture2D> GetTexture2D(string url, int version = 0, Hash headers = null, IProgress<float> progress = null)
        {
            return GetAsset<Texture2D>(url, version.ToString(), headers, progress, (observer, www, request, local) =>
            {
                Texture2D texture = null;
                if (www != null)
                {
                    texture = new Texture2D(0,0);
                    texture.LoadImage(www.bytes);
                }
                else
                {
                    texture = request.asset as Texture2D;
                }
                texture.name = url;
                observer.OnNext(texture);
                texture = null;
            });
        }

        public static IObservable<Texture2D> GetTexture2D(string url, string md5, Hash headers = null, IProgress<float> progress = null)
        {
            return GetAsset<Texture2D>(url, md5, headers, progress, (observer, www, request, local) =>
            {
                Texture2D texture = null;
                if (www != null)
                {
                    texture = new Texture2D(0, 0);
                    texture.LoadImage(www.bytes);
                }
                else
                {
                    texture = request.asset as Texture2D;
                }
                texture.name = url;
                observer.OnNext(texture);
                texture = null;
            });
        }


        public static IObservable<QTexture2D> GetQTexture2D(string url, int version = 0, Hash headers = null, IProgress<float> progress = null)
        {
            return GetAsset<QTexture2D>(url, version.ToString(), headers, progress, (observer, www, request,local) =>
            {
                Texture2D texture=null;
                AssetLocation assetLocation= AssetLocation.Resources;
                if (www != null)
                {
                    assetLocation = local ? AssetLocation.Local : AssetLocation.Web;
                    texture = new Texture2D(0,0);
                    texture.LoadImage(www.bytes);
                }
                else
                {
                    texture = request.asset as Texture2D;
                }
                texture.name = url;
                QTexture2D qTexture2D = new QTexture2D(texture, assetLocation);
                observer.OnNext(qTexture2D);
                texture = null;
            });
        }

        public static IObservable<QTexture2D> GetQTexture2D(string url, string md5, Hash headers = null, IProgress<float> progress = null)
        {
            return GetAsset<QTexture2D>(url, md5, headers, progress, (observer, www, request,local) =>
            {
                Texture2D texture = null;
                AssetLocation assetLocation = AssetLocation.Resources;
                if (www != null)
                {
                    assetLocation = local ? AssetLocation.Local : AssetLocation.Web;
                    texture.LoadImage(www.bytes);
                }
                else
                {
                    texture = request.asset as Texture2D;
                }
                texture.name = url;
                QTexture2D qTexture2D = new QTexture2D(texture, assetLocation);
                observer.OnNext(qTexture2D);
                texture = null;
            });
        }

        static IObservable<T> GetAsset<T>(string url, string version, Hash headers, IProgress<float> progress, Action<IObserver<T>, WWW, ResourceRequest,bool> completed)
        {
            if (File.Exists(url))//在本地目录
            {
                return ObservableUnity.FromCoroutine<T>((observer, cancellation) => FetchBytes(new WWW(url, null, (headers ?? new Hash())), string.Empty, observer, progress, cancellation, (www,local) => completed(observer, www, null,local)));
            }
            else if (url.IndexOf(Http) != -1)//在网络
            {
                var filePath = GetSavePath(url, version);
                if (File.Exists(filePath)) url = filePath;
                return ObservableUnity.FromCoroutine<T>((observer, cancellation) => FetchBytes(new WWW(url, null, (headers ?? new Hash())), filePath, observer, progress, cancellation, (www, local) => completed(observer, www, null, local)));
            }
            else//在Resources
            {
                return ObservableUnity.FromCoroutine<T>((observer, cancellation) => FetchResources<T>(Resources.LoadAsync(url), observer, progress, cancellation, request => completed(observer, null, request, false)));
            }
        }


        static IEnumerator FetchResources<T>(ResourceRequest request, IObserver<T> observer, IProgress<float> reportProgress, CancellationToken cancel, Action<ResourceRequest> completed)
        {
            if (reportProgress != null)
            {
                while (request.isDone)
                {
                    try
                    {
                        reportProgress.Report(request.progress);
                    }
                    catch (Exception ex)
                    {
                        observer.OnError(ex);
                        yield break;
                    }

                    yield return null;
                }
            }
            else
            {
                if (!request.isDone)
                {
                    yield return request;
                }
            }

            if (cancel.IsCancellationRequested)
            {
                yield break;
            }

            if (reportProgress != null)
            {
                try
                {
                    reportProgress.Report(request.progress);
                }
                catch (Exception ex)
                {
                    observer.OnError(ex);
                    yield break;
                }
            }
            if (request.asset == null)
            {
                observer.OnError(new ResourcesErrorException(request));
            }
            else
            {
                completed(request);
                observer.OnCompleted();
            }
        }

        static IEnumerator FetchBytes<T>(WWW www, string savePath, IObserver<T> observer, IProgress<float> reportProgress, CancellationToken cancel, Action<WWW,bool> completed)
        {
            using (www)
            {
                if (reportProgress != null)
                {
                    while (!www.isDone && !cancel.IsCancellationRequested)
                    {
                        try
                        {
                            reportProgress.Report(www.progress);
                        }
                        catch (Exception ex)
                        {
                            observer.OnError(ex);
                            yield break;
                        }
                        yield return null;
                    }
                }
                else
                {
                    if (!www.isDone)
                    {
                        yield return www;
                    }
                }

                if (cancel.IsCancellationRequested)
                {
                    yield break;
                }

                if (reportProgress != null)
                {
                    try
                    {
                        reportProgress.Report(www.progress);
                    }
                    catch (Exception ex)
                    {
                        observer.OnError(ex);
                        yield break;
                    }
                }

                if (!string.IsNullOrEmpty(www.error))
                {
                    observer.OnError(new WWWErrorException(www, www.text));
                }
                else
                {
                    bool local = true;
                    if (www.url.IndexOf(Http) != -1)
                    {
                        local = false;
                        try
                        {
                            var dirName = Path.GetDirectoryName(savePath);
                            if (Directory.Exists(dirName))
                            {
                                var fileName = Path.GetFileName(savePath).Split(Aite);
                                if (fileName.Length == 2)
                                {
                                    var dir = new DirectoryInfo(dirName);
                                    var files = dir.GetFiles(string.Format(GetFilesFormat, fileName[1]));
                                    for (int count = files.Length, i = 0; i < count; i++)
                                    {
                                        File.Delete(files[i].ToString());
                                    }
                                }
                            }
                            else
                            {
                                Directory.CreateDirectory(dirName);
                            }
                            File.WriteAllBytes(savePath, www.bytes);
                        }
                        catch (Exception ex)
                        {
                            observer.OnError(ex);
                            yield break;
                        }
                    }
                    completed(www,local);
                    observer.OnCompleted();
                }
            }
        }

        static string GetSavePath(string url, string version)
        {
            var fileName = GetWritePath(string.Empty) + Regex.Replace(url, UrlRegex, string.Empty);
            return string.Format(GetSavePathFormat, Path.GetDirectoryName(fileName), version, Path.GetFileName(fileName));
        }

        static string GetWritePath(string dir)
        {
            string path;
            switch (Application.platform)
            {
                case RuntimePlatform.WindowsPlayer:
                case RuntimePlatform.WindowsEditor:
                case RuntimePlatform.OSXEditor:
                    path = string.Format(Path1, Application.dataPath.Replace(Path2, string.Empty), dir);
                    break;
                case RuntimePlatform.IPhonePlayer:
                case RuntimePlatform.Android:
                default:
                    path = string.Format(Path3, Application.persistentDataPath, dir);
                    break;
            }
            var dirName = Path.GetDirectoryName(path);
            if (!Directory.Exists(dirName)) Directory.CreateDirectory(dirName);
            return path;
        }
    }


    public class ResourcesErrorException : Exception
    {
        public string RawErrorMessage { get; private set; }
        public ResourceRequest Request { get; private set; }
        static readonly string text = "Unable to find resources";

        public ResourcesErrorException(ResourceRequest request)
        {
            this.Request = request;
            this.RawErrorMessage = text;
        }

        public override string ToString()
        {
            return text;
        }
    }
}

Tools

using UnityEngine;

public static class Tools  {
    
    public static Vector2 ScaleScaling(Vector2 size, float width, float height)
    {
        if (size.x / size.y <= width / height)
            return new Vector2(size.x, size.x / width * height);
        else
            return new Vector2(size.y * (width / height), size.y);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_17813937/article/details/82802241