之前在測驗怎樣運行 WebGL 的時候使用了遠程加載檔案進行測驗 : 發布WebGL的程序
因為對瀏覽器不是很熟悉, 現在用編輯器模式直接跑一下, 來看看 UnityWebRequest 的下載和快取, 我使用了一個叫 WebGL_Test 的工程, 然后獲取它的編輯器下的快取目錄看看 :
[MenuItem("Tools/Test")] public static void Test() { Debug.Log(Caching.currentCacheForWriting.path); }
C:/Users/XXXX/AppData/LocalLow/Unity/DefaultCompany_WebGL_Test
UnityEngine.Debug:Log(Object)
這是一般的快取路徑, 不過看到它的檔案夾是一個 PlayerSettings 里面的設定拼接成的檔案夾 :

通過遠程方式加載 AssetBundle 檔案之后, 再看看它在本地進行了怎樣的快取 :


跟加載的 AssetBundle 名稱一樣, 它創建了對應名稱的檔案夾, 而且是直接在根目錄創建的, 沒有按照 AssetBundle 包的相對路徑來, 進去看之后發現它還是以檔案夾的形式來對應哈希值 :


而最后的這些快取檔案 __data 應該就是快取的 AssetBundle了, 因為在服務器上的是一模一樣的大小 :

它跟 WebGL 通過瀏覽器查看的 IndexedDB 中的快取也是一樣的結構 :

上面的截圖是幾天前打的包, 這個測驗是今天測驗的新打的包, 不過它們的哈希值仍然是 af448c54de9e2c7cff2cb90e8367cdde 沒有變, 說明它可以通過哈希值做穩定的增量更新.
現在我在場景里面添加幾個 Cube 讓場景發生一些改變, 再打包到服務器上, 看看本地快取會怎樣變化 :

從新的 AssetBundleManifest 里面獲取的哈希值已經變了 :

而新的檔案也被快取到了本地 :


相應的快取檔案.
至于那個 __lock 的檔案, 在我停止運行編輯器之后它就消失了, 應該是一個保護標記, 在相應的 AssetBundle 包被加載之后就會產生, 防止運行時被洗掉?

這是停止運行后 __lock 檔案被洗掉了.
而上一個版本的 s1 快取檔案也還是存在的 :

既然這樣, 那就可以猜測其實 UnityWebRequest 或者 WWW.LoadFromCacheOrDownload 的下載和快取邏輯其實挺簡單的, 就是從服務器 GET 請求來一個二進制檔案, 然后獲取 AssetBundle, 至于編碼之類的通過HTTP協議來完成, 解壓邏輯通過 AssetBundle 相關 API 來完成, 他就是一個 HTTP 請求的封裝, 所以它既可以作為普通請求使用, 又能進一步直接獲取到 AssetBundle 物件 :

既然本地快取已經下載好相關包的話, 能不能通過同步讀取的方式加載呢? 測驗一下 :
var s1_hash = assetbundleManifest.GetAssetBundleHash("scenes/s1.assetbundle"); var loadPath = Caching.currentCacheForWriting.path + "/s1/" + s1_hash + "/__data"; Debug.Log(loadPath); var s1 = AssetBundle.LoadFromFile(loadPath); if(s1) { UnityEngine.SceneManagement.SceneManager.LoadScene("S1", UnityEngine.SceneManagement.LoadSceneMode.Single); }
assetbundleManifset 是最新打包出來的 AssetBundleManifest 了, 讀取出來沒有問題:
C:/Users/XXXX/AppData/LocalLow/Unity/DefaultCompany_WebGL_Test/s1/ba52a9babc43ca063d143489ece6523d/__data

所以這個加載程序還是可以進一步封裝的, 如果本地快取有相應的檔案的話, 也是可以同步讀取的, 不過這里說的是PC的情況, 因為它是直接快取了檔案, 然后看看在瀏覽器中的快取 :

只加載了一個 s1 場景, 沒有其它, 這樣一個檔案如果沒有相應的API的話, 是讀取不到的了......
既然這樣再折騰一下, 看看這個 IndexedDB 是否能進行操作, 直接在已經生成的 WebGL 主頁面上加代碼 :
<!DOCTYPE html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Unity WebGL Player | WebGL_Test</title> <link rel="shortcut icon" href="TemplateData/favicon.ico"> <link rel="stylesheet" href="TemplateData/style.css"> <script src="TemplateData/UnityProgress.js"></script> <script src="Build/UnityLoader.js"></script> <script> var gameInstance = UnityLoader.instantiate("gameContainer", "Build/WebGL Built.json", { onProgress: UnityProgress }); function TestDB() { var request = window.indexedDB.open("/idbfs"); request.onsuccess = function (event) { var db = request.result; console.log('資料庫打開成功'); var objectStore = db.transaction('FILE_DATA').objectStore('FILE_DATA'); objectStore.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { console.log('key: ' + cursor.key); console.log('mode: ' + cursor.value.mode); cursor.continue(); } else { console.log('沒有更多資料了!'); } }; }; } </script> </head> <body> <button type="button" onclick="TestDB()">TestDB</button> <div class="webgl-content"> <div id="gameContainer" style="width: 960px; height: 600px"></div> <div class="footer"> <div class="webgl-logo"></div> <div class="fullscreen" onclick="gameInstance.SetFullscreen(1)"></div> <div class="title">WebGL_Test</div> </div> </div> </body> </html>

這里顯示它的名稱為 /idbfs 我們就用它作為資料庫名稱了, 然后他的表名就用下面的 FILE_DATA 進行資料庫厲遍, 使用 transaction 的方式保證安全性, 它的 key 和 value 里面的 mode 比較可讀, 列印出來 :

Log :


可見確實就是在這個資料庫里面了 OK.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/189249.html
標籤:其他
