WebGL AssetBundle 加载 缓存

U3D的AssetBundle真的是博(坑)大精(坑)深啊

安卓的话要先打包到StreamingAssetPath中,安装后第一次运行,自动把Streaming 中的解压到PersistentDataPath中,因为persistent目录是在运行过一次才创建的。

这样,之后再更新资源就直接下载到persistent目录下了

但是,WebGL项目呢

这个就不存在什么streaming或者persistent了,因为不能加载本地路径

所以就只有缓存,加载包时就要用

WWW.LoadFromDownloadOrCache(url, version)

这样会把资源下载到缓存目录中,每次加载时会判断版本,相同则直接从本地磁盘加载,不然才从网络下载,更新本地磁盘中的缓存。

这里坑就来了,就是这个版本号。第一次加载还好,随便设置个数,因为本地没有么,直接下载了。以后呢,怎么判断本地的版本和服务器的版本呢?

之所以有这个问题,是因为这个版本号是加载时写在程序里的,比如说第一次下载后,会把各包加载时的这个版本号也记录在本地缓存里,下次再加载时,程序里设置的版本号会与本地缓存中之前记录的版本号对比,如果不同,则说明有更新,下载包覆盖本地缓存,再加载,如果一样则没有更新,不下载,直接加载本地缓存。

看了很多例子,都是简单的写个0或者1,哪怕服务器端资源更新了,如果这个版本号还是用的和上次一样的,就认为没有更新,也不会从网络下载。

那么得想办法动态的获取包的这个版本,那么

WWW.LoadFromDownloadOrCache(url, version)

这个重载方法就不合适了,因为这个version没找到办法获取……
文档里说的是这个version要自增,也就是新的version要大于老的才更新,不过看网上有人说只要版本号不同,就更新,无论是大于还是小于,这个没试过,不过也无所谓了。

看了一眼,这个加载方法的另一项重载是:

public static WWW LoadFromCacheOrDownload(string url, Hash128 hash, uint crc);

说明:以下只是目前的一个设想,没有实践

首先说最后一个参数crc,按文档里说的,这个值非0时则对比crc,目前不关心这个,就让它是0
最重要的就是第二个参数hash
文档解释:

hash    Hash128 which is used as the version of the AssetBundle.

对比这个可以相当于version版本。
那好,想办法得到各assetbundle包的Hash128

从manifest文件下手,打包之后会有个总的manifest文件,和你的包的根目录名同名
比如打包在StreamingAssets下,则其目录下有一个StreamingAssets.manifest文件

using(WWW www=WWW.LoadFromDownloadOrCache("..../StreamingAssets/StreamingAssets"))
{
        yield return www;
        AssetBundle ab=www.assetBundle;
        AssetBundleManifest abm=ab.loadAsset<AssetBundleManifest>("AssetBundleManifest");
        string[] bundleNames=abm.GetAllAssetBundles();
        foreach(string item in bundleNames)
        {
                Hash128 hash = abm.GetAssetBundleHash(item);
        }
}

如上,GetAllAssetBundles()可以得到所有包的包名
再用GetAssetBundleHash(包名)得到包对应的hash128

那么每次加载资源之前,先把包的Hash128获取到,再用

public static WWW LoadFromCacheOrDownload(string url, Hash128 hash, uint crc);

这样每次加载都会对比这个Hash128值,这个就相当于是版本了

我试了一下,在开发环境下,如果资源没有任何修改,反复打包,出来的这个Hash128是不变的,如果有修改,比如材质的颜色变化一下,prefab的scale变化一下之类的,再打出来的包,Hash128就变化了。

理论上说,这样LoadFromDownloadOrCache就可以判断出有没有更新了

所以,每次打开程序,首先加载总的manifest,把包和对应的Hash128存到一个地方,比如字典

Dictionary<string, Hash128> bundleHashDict = new Dictionary<string, Hash128>();
using(WWW www=WWW.LoadFromDownloadOrCache("..../StreamingAssets/StreamingAssets"))
{
        yield return www;
        AssetBundle ab=www.assetBundle;
        AssetBundleManifest abm=ab.loadAsset<AssetBundleManifest>("AssetBundleManifest");
        string[] bundleNames=abm.GetAllAssetBundles();
        foreach(string item in bundleNames)
        {
                Hash128 hash = abm.GetAssetBundleHash(item);
                bundleHashDict.Add(item, hash);
        }
}

要加载一个名叫“a.assetbundle"的包

string path = "...../a.assetbundle";
Hash128 hash=bundleHashDict["a.assetbundle"];
using(WWW www = WWW.LoadFromDownloadOrCache(path, hash, 0))
{
        yield return www;
        .........
}

如上,根据包名在字典里取得其之前获取并存入字典里的Hash128,作为LoadFromDownloadOrCache方法的第二个参数,理论上会与本地缓存最后一次更新下载时存储的包的Hash128(在上一次调用此方法时写入缓存的)进行对比,相同则不更新,不同则更新。

理论上如此,有待实践

原文地址:http://blog.51cto.com/shuxiayeshou/2136680

时间: 2024-11-10 07:41:35

WebGL AssetBundle 加载 缓存的相关文章

AssetBundle加载API

AssetBundle加载API 在Unity 5当中,可以通过4个不同的API来加载AssetBundle,4个API可以用两个条件来区分: AssetBundle是 LZMA压缩. LZ4压缩还是不压缩的 加载AssetBundle的平台 这4个API分别是: AssetBundle.LoadFromMemoryAsync AssetBundle.LoadFromFile WWW.LoadFromCacheOrDownload UnityWebRequest 的 DownloadHandle

关于ViewPager的适配器之——pagerAdapter加载缓存页面的机制

ViewPager有很多的适配器,如pagerAdapter,FragmentPagerAdapter等, 今天我想重点谈的是关于pagerAdapter加载缓存页面的机制的问题. 首先,使用pagerAdapter一般需要重写它的四个未实现的方法分别是: 1.  getCount(){} //得到总数 2.    //实例化页面,  相当于BaseAdapter等适配器中的 getView()方法 返回想要显示的对象(内容) // 不同之处是:这里需要把这些对象(内容)一一添加到adapter

android网络图片加载缓存,避免重复加载。

1.主线程调用方法: imageView = new ImageView(this); AsynImageLoader asynImageLoader = new AsynImageLoader(); asynImageLoader.showImageAsyn(imageView, URL, R.drawable.nopicture); mViewList.add(imageView); 2.AsynImageLoader加载缓存:     public void showImageAsyn(I

关于unity 中使用AssetBundle加载资源,shader偶尔会丢失的问题解决办法

问题描述: 因为项目中要进行热更新设计,所以用unity官方推荐的打包方式assetbundle进行打包,打包好了以后再电脑上运行正常,但是当发布到android上后发现偶尔场景背景会出现空白,多方查找,发现unity存在使用assetbundle加载资源会丢失shader的问题.网上找了一些解决方式,测试可用,分享出来. 方案一:(亲测可用) 第一步,在将用到的Shader加到Editor->Graphics Settings的Shader列表里再进行打包(依赖打包) 第二步,在代码中给sha

Android-Universal-Image-Loader (图片异步加载缓存库)对Bitmap的优化处理

转载请注明出处:http://blog.csdn.net/u011733020 前言: 前面两篇分别介绍了: Android-Universal-Image-Loader (图片异步加载缓存库)的使用配置 Android-Universal-Image-Loader (图片异步加载缓存库)的源码解读 通过前两篇,我们了解了 UIL的使用配置,UIL将服务器上的一张图片保存到本地,加载到内存的过程,以及UIL对DiscCache和MemoryCache的策略,但是还有一部分比较重要,因为它是我们的

WebGL 启动加载触发更新流程分析

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. requestAnimFrame(tick); 此命令是 HTML5 中新增的用于替换定时器触发更新的命令,以实现动画更新,其后台实现有一特殊之处

Oracle Coherence中文教程二十:预加载缓存

预加载缓存 本章介绍了不同的模式,你可以用它来预加载缓存.该模式包括批量装载和分布载荷. 本章包含以下各节: 执行批量加载和处理 执行分布式批量加载 20.1执行批量加载和处理 例20-5, PagedQuery.java ,演示了在一个连贯缓存技术,有效地批量加载和处理项目. 20.1.1批量写入缓存 使用连贯性时,一个常见的场景是预先填充缓存应用程序使用它之前.一个简单的方法来做到这例20-1中的Java代码所示: 例20-1预加载缓存 public static void bulkLoad

Android 网络图片加载缓存处理库ImageLoader和Picasso

在Android图片处理中需要考虑的问题很多,例如OOM.图片缓存和网络图片加载.多线程问题及图片压缩处理等等复杂的问题.网上也有一些很优秀的开源库帮我们处理这些问题,下面介绍两款开源图片处理库框架:Universal-ImageLoader和Picasso. Universal-ImageLoader: 优点: 支持本地图片和网络图片的多线程异步加载和缓存处理: 个性化的配置自己项目的ImageLoader: 图片加载过程的监听回调: 自动对加载的图片针对当前剩余内存进行裁剪优化,防止OOM:

聊聊Android优秀的图片加载缓存的开源框架?UIL、Glide、Picasso

今天总结下有关Android的图片开源框架UIL.Glide.Picasso.当然不止这些还有okhttp.xutlis.afinal.andbase.volley等等,今天主要是对于Glide使用进行总结. Glide是谷歌推荐使用的加载图片的框架,它相对于其他的框架有更多的有点,说到Glide我们不得不谈谈Picasso,为什么呢?这是因为Picasso的使用与Glide的使用上非常的相似,但是细细看,有明显不同,首先我们看下Picasso与Glide的基本用法? Picasso: 1 Pi