zoukankan      html  css  js  c++  java
  • 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=" 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.

      

      

       

      

  • 相关阅读:
    关于sqrt函数的使用
    电子商务
    随笔
    哈哈
    整体管理
    软件产品质量特性
    问题
    风险
    antd
    Flex布局大作用
  • 原文地址:https://www.cnblogs.com/tiancaiwrk/p/13391376.html
Copyright © 2011-2022 走看看