Unity 遠程加載資源以及本地緩存相關

  以前在測試怎樣運行 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.

相關文章
相關標籤/搜索