有人说使用unity 的WWW类的LoadFromCacheOrDownload方法就可以实现缓存加载的方式,但是我自己使用的时候发现在unity编辑器环境下是可以的,但是到Android和iOS平台下就会有问题,会导致每次进入资源都是从网络上下载,严重影响效率,所以有了这篇文章
首先说一下整体的设计思路,项目中有很多资源,如模型,声音等,是从服务端下载下来的,所以在每次使用资源的时候先判断当前的缓存的目录里面是否有资源,有则从本地缓存加载,没有的话再去服务端下载,并缓存到本地。设计思路有了,那么接下来就是一步步实现。
创建一个类,就叫CachedDownloader,包含的方法如下
static long GetInt64HashCode(string strText)
{
var s1 = strText.Substring(0, strText.Length / 2);
var s2 = strText.Substring(strText.Length / 2);
var x= ((long)s1.GetHashCode()) << 0x20 | s2.GetHashCode();
return x;
}
static bool CheckFileOutOfDate(string filePath)
{
System.DateTime written = File.GetLastWriteTimeUtc(filePath);
System.DateTime now = System.DateTime.UtcNow;
double totalHours = now.Subtract(written).TotalHours;
return (totoalHours>300);
}
static IEnumerator DoLoad(WWW www, string filePath, bool web)
{
yield return www;
if (www.error == null)
{
if (web)
{
Debug.Log("SAVING DOWNLOAD " + www.url + " to " + filePath);
File.WriteAllBytes(filePath, www.bytes);
Debug.Log("SAVING DONE " + www.url + " to " + filePath);
}
else
{
Debug.Log("SUCCESS CACHE LOAD OF " + www.url);
}
}
else
{
if (!web)
{
File.Delete(filePath);
}
Debug.Log("WWW ERROR " + www.error);
}
}
static public WWW GetCachedWWW(string url)
{
string filePath;
#if UNITY_EDITOR
filePath = Application.dataPath + "/temp";
#else
filePath = Application.persistentDataPath;
#endif
//使用文件名的hashCode作为资源名称
if (url.EndsWith(".mp3"))
{
filePath += "/" + GetInt64HashCode(url) + ".mp3";
}
else
{
filePath += "/" + GetInt64HashCode(url);
}
bool web = false;
WWW www;
bool useCached = false;
useCached = System.IO.File.Exists(filePath) && !CheckFileOutOfDate(filePath);
//使用缓存路径
if (useCached)
{
string pathforwww = "file://" + filePath;
Debug.Log("TRYING FROM CACHE " + url + " file " + pathforwww);
www = new WWW(pathforwww);
}
//使用服务端路径
else
{
web = true;
www = new WWW(url);
}
CachedTextureDownloader.Instance.StartCoroutine(DoLoad(www, filePath, web));
return www;
}
其中GetInt64HashCode是为了获取hashCode作为文件名的,而在判断到底是否使用服务端路径那里用了一个CheckFileOutOfDate来判断文件是否过期,这个并不是绝对条件,可以根据自己的业务需求去更改,(比如可以不依赖创建的时间而依赖其他判断条件,或者修改认为过期的时间小时数等,总之是为了让资源重新去下载的限制条件,有些像AssetBundle里的版本号)Doload方法是判断好是否使用服务端下载后,实际创建http请求下载的方法。
类写好以后在实际使用的地方调用类的GetCachedWWW方法,传入你要下载的资源的地址即可