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


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

  

 

  

   

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM