扩展一下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);
}
}