以前在測試怎樣運行 WebGL 的時候使用了遠程加載文件進行測試 : 發佈WebGL的過程css
由於對瀏覽器不是很熟悉, 如今用編輯器模式直接跑一下, 來看看 UnityWebRequest 的下載和緩存, 我使用了一個叫 WebGL_Test 的工程, 而後獲取它的編輯器下的緩存目錄看看 : html
[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 裏面的設置拼接成的文件夾 : web
經過遠程方式加載 AssetBundle 文件以後, 再看看它在本地進行了怎樣的緩存 : 數據庫
跟加載的 AssetBundle 名稱同樣, 它建立了對應名稱的文件夾, 並且是直接在根目錄建立的, 沒有按照 AssetBundle 包的相對路徑來, 進去看以後發現它仍是以文件夾的形式來對應哈希值 : json
而最後的這些緩存文件 __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.