溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

WebGL AssetBundle 加載 緩存

發(fā)布時(shí)間:2020-08-01 21:19:30 來源:網(wǎng)絡(luò) 閱讀:5297 作者:lreach 欄目:游戲開發(fā)

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

安卓的話要先打包到StreamingAssetPath中,安裝后第一次運(yùn)行,自動(dòng)把Streaming 中的解壓到PersistentDataPath中,因?yàn)閜ersistent目錄是在運(yùn)行過一次才創(chuàng)建的。

這樣,之后再更新資源就直接下載到persistent目錄下了

但是,WebGL項(xiàng)目呢

這個(gè)就不存在什么streaming或者persistent了,因?yàn)椴荒芗虞d本地路徑

所以就只有緩存,加載包時(shí)就要用

WWW.LoadFromDownloadOrCache(url, version)

這樣會(huì)把資源下載到緩存目錄中,每次加載時(shí)會(huì)判斷版本,相同則直接從本地磁盤加載,不然才從網(wǎng)絡(luò)下載,更新本地磁盤中的緩存。

這里坑就來了,就是這個(gè)版本號(hào)。第一次加載還好,隨便設(shè)置個(gè)數(shù),因?yàn)楸镜貨]有么,直接下載了。以后呢,怎么判斷本地的版本和服務(wù)器的版本呢?

之所以有這個(gè)問題,是因?yàn)檫@個(gè)版本號(hào)是加載時(shí)寫在程序里的,比如說第一次下載后,會(huì)把各包加載時(shí)的這個(gè)版本號(hào)也記錄在本地緩存里,下次再加載時(shí),程序里設(shè)置的版本號(hào)會(huì)與本地緩存中之前記錄的版本號(hào)對(duì)比,如果不同,則說明有更新,下載包覆蓋本地緩存,再加載,如果一樣則沒有更新,不下載,直接加載本地緩存。

看了很多例子,都是簡單的寫個(gè)0或者1,哪怕服務(wù)器端資源更新了,如果這個(gè)版本號(hào)還是用的和上次一樣的,就認(rèn)為沒有更新,也不會(huì)從網(wǎng)絡(luò)下載。

那么得想辦法動(dòng)態(tài)的獲取包的這個(gè)版本,那么

WWW.LoadFromDownloadOrCache(url, version)

這個(gè)重載方法就不合適了,因?yàn)檫@個(gè)version沒找到辦法獲取……
文檔里說的是這個(gè)version要自增,也就是新的version要大于老的才更新,不過看網(wǎng)上有人說只要版本號(hào)不同,就更新,無論是大于還是小于,這個(gè)沒試過,不過也無所謂了。

看了一眼,這個(gè)加載方法的另一項(xiàng)重載是:

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

說明:以下只是目前的一個(gè)設(shè)想,沒有實(shí)踐

首先說最后一個(gè)參數(shù)crc,按文檔里說的,這個(gè)值非0時(shí)則對(duì)比crc,目前不關(guān)心這個(gè),就讓它是0
最重要的就是第二個(gè)參數(shù)hash
文檔解釋:

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

對(duì)比這個(gè)可以相當(dāng)于version版本。
那好,想辦法得到各assetbundle包的Hash228

從manifest文件下手,打包之后會(huì)有個(gè)總的manifest文件,和你的包的根目錄名同名
比如打包在StreamingAssets下,則其目錄下有一個(gè)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)
        {
                Hash228 hash = abm.GetAssetBundleHash(item);
        }
}

如上,GetAllAssetBundles()可以得到所有包的包名
再用GetAssetBundleHash(包名)得到包對(duì)應(yīng)的hash228

那么每次加載資源之前,先把包的Hash228獲取到,再用

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

這樣每次加載都會(huì)對(duì)比這個(gè)Hash228值,這個(gè)就相當(dāng)于是版本了

我試了一下,在開發(fā)環(huán)境下,如果資源沒有任何修改,反復(fù)打包,出來的這個(gè)Hash228是不變的,如果有修改,比如材質(zhì)的顏色變化一下,prefab的scale變化一下之類的,再打出來的包,Hash228就變化了。

理論上說,這樣LoadFromDownloadOrCache就可以判斷出有沒有更新了

所以,每次打開程序,首先加載總的manifest,把包和對(duì)應(yīng)的Hash228存到一個(gè)地方,比如字典

Dictionary<string, Hash228> bundleHashDict = new Dictionary<string, Hash228>();
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)
        {
                Hash228 hash = abm.GetAssetBundleHash(item);
                bundleHashDict.Add(item, hash);
        }
}

要加載一個(gè)名叫“a.assetbundle"的包

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

如上,根據(jù)包名在字典里取得其之前獲取并存入字典里的Hash228,作為LoadFromDownloadOrCache方法的第二個(gè)參數(shù),理論上會(huì)與本地緩存最后一次更新下載時(shí)存儲(chǔ)的包的Hash228(在上一次調(diào)用此方法時(shí)寫入緩存的)進(jìn)行對(duì)比,相同則不更新,不同則更新。

理論上如此,有待實(shí)踐

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI