首页 首页 资讯 泰斗译馆 查看内容

Unity WebGL内存优化:Deux部分

2017-8-15 14:10| 发布者: guangling| 查看: 379| 评论: 0|原作者: 青春L

摘要: Unity WebGL内存优化:Deux部分现在Unity 已经是过去的一件事了,确保你的Unity WebGL的内容顺畅运行比以往任何时候都更加重要。我们从开发人员那里听到的最主要的痛点是,当用户试图玩WebGL游戏时,他们会遇到可怕 ...
Unity WebGL内存优化:Deux部分
现在Unity 已经是过去的一件事了,确保你的Unity WebGL的内容顺畅运行比以往任何时候都更加重要。我们从开发人员那里听到的最主要的痛点是,当用户试图玩WebGL游戏时,他们会遇到可怕的“内存不足”错误。对于使用32位版本的浏览器的玩家来说,这是一个特别令人沮丧的问题,因为对于Unity堆来说,他们不太可能有一个大的连续的空闲内存块。

本文将介绍一些关于诊断和解决与您的Unity WebGL游戏相关的内存问题的技巧和知识。
监控内存使用
在分析和优化您的Unity WebGL游戏时,重要的是要跟踪多种内存使用情况。第一个是Unity堆,它默认为256MB,可以在“WebGL内存大小”的发布设置界面中更改。在之前的一篇博客文章中,我们谈到了这段内存的一些优化技术(以及为什么要尽量保持它的最小)。重申一下,为了Unity堆需要保留的内存越少,浏览器对音频、IndexedDB数据库等其他东西的内存就越多。

由于减小您的Unity堆的大小非常重要,我们已经为我们的WebGL实用程序包添加了一个非常简单的内存统计类(基于Unity团队的优秀blog),以便帮助开发人员跟踪这些信息并将其报告给浏览器控制台。

简单地将这个包导入到您的Unity项目中,在您的场景中添加“WebGL内存统计”脚本,并且在您选择的时间间隔内,在您的浏览器控制台中记录关于free/total的日志条目。
211759v9y20bh0h4hhhh5h.png.thumb.jpg
WebGL内存数据配置
需要注意的是,这里提供的数据单元/emscripten似乎是内存使用的一个高水位标志。也就是说,当对象被清理时,使用/释放的内存不会改变。但是,作为度量和调优为您的Unity堆分配多少内存的工具,它仍然是至关重要的。您应该使用这个工具来跟踪所使用的最高内存,然后在上面添加一个安全网,然后将其四舍五入到下一个最高的16MB。

在本例中,您可以看到,当我们真正应该请求32MB时,我们的应用程序正在请求一个高达256MB(默认)的堆:
211759rzttr1qznttccxt4.png.thumb.jpg
另一个与内存相关的问题是Unity使用的IndexedDB文件系统。每当您缓存一个资源包或使用任何与文件系统相关的方法时,它们都存储在一个由IndexedDB支持的虚拟文件系统中。

您可能没有意识到的是,当您的Unity应用程序启动时,这个虚拟文件系统将被加载到内存中并持久存储在内存中。这意味着,如果您正在为资源包使用默认的Unity缓存机制,那么您将把所有这些bundle的大小添加到您的游戏的内存需求中,即使它们没有被加载。

您可以使用开发人员工具的“Application”选项卡来跟踪这个内存使用情况。正如您在这里看到的,在缓存中存储了几个包,而选中的包则接近20MB:
211759oh165w77vf1eh157.png.thumb.jpg
为了查看这对总内存消耗的影响,我们可以使用Chrome(或Firefox)在应用程序生命周期的不同时间点上获取堆快照。对于这个演示,当应用程序第一次加载并没有缓存时,我们将第一次快照,然后在加载了一些大的资源包之后,再一次重新加载页面之后。

您可以看到,在初始加载之后,我们使用了大约230MB的内存。在加载完所有的资源包后,我们的大小为300MB,然后在重新加载页面(但不是资源包)之后,我们仍然接近300MB。这是不好的。

幸运的是,Unity团队的优秀人员让我们覆盖了一个名为CachedXMLHttpRequest的addon。当与非缓存的UnityWebRequest调用结合使用时,CachedXMLHttpRequest使用一个单独的IndexedDB缓存来存储在内存中不保持持久的下载文件,从而导致内存使用量减少。在使用CachedXMLHttpRequest时,让我们看一下我们的示例:
211759f4zssd6zdk6is4k8.png.thumb.jpg
内存使用大约在236MB左右,然后在加载和缓存资源包时,最多可达237MB,然后在页面重新加载后回到226MB。这是非常棒的,因为我们已经消除了IndexedDB虚拟文件系统造成的永久内存膨胀。
211759kawrdzad3yr8ybda.png.thumb.jpg
重要的是要注意,当使用CachedXMLHttpRequest WebGL堆使用情况可以增加由于包的处理方式都不相同,所以你应该小心不要负载太多包)(这是一个最佳实践,同时,总是确保当你完成卸载它们。对于本文来说,优化资源包有点不太适用,但是一般来说,您希望尽可能地使它们粒度更细,这样您就不会将未使用的资源保存在内存中,并避免由于加载大型资源包而导致的内存峰值。

Kongregate WebGL实用程序包
不幸的是,最初版本的CachedXMLHttpRequest有几个bug:

Firefox私有浏览模式下显示一个错误对话框
在iframe中使用Safari时,插件是不实用的
同步XHR请求用于重新验证资源

我们已经发布了一个更新的版本,作为WebGL实用程序包的一部分,它是一个替代,解决了前面提到的问题,并添加了以下功能:

支持异步查询来自Unity的缓存,以确定一个项目是否存在
添加了为不应该缓存的项目配置黑名单和不应该重新验证的项目的能力
允许从Unity中清除缓存

我们将尝试与Unity WebGL团队联系,将这些特性合并到正式的插件中,正如我们在将几个项目转换为CachedXMLHttpRequest时所发现的那样。

转换成CachedXMLHttpRequest
如果你打算把你的项目使用CachedXMLHttpRequest,您可能会希望使用缓存类上的方法来清理你的先前缓存的资源包或设置的最大磁盘空间用于IndexedDB低量,以确保你的旧资源不占用任何空间磁盘或内存中。

如果要删除缓存,则需要在访问任何资源包或其他文件之前进行,理想情况下是在初始场景中存在的game对象的清醒方法。我们发现,在一些统一的版本中,克兰希奇方法可能是不可靠的。在这种情况下,您可以使用以下代码直接使用IndexedDB来清除缓存,但是需要注意的是,这将清除整个域的缓存。这应该插入到您的WebGL索引中。在包含Unity加载器之前,html或模板。
[AppleScript] 纯文本查看 复制代码
(function clearCache() {
  var idb = window.indexedDB || window.mozIndexedDB ||
            window.webkitIndexedDB || window.msIndexedDB;
  if (!idb) return;

  var open;
  try { open = idb.open('/idbfs') } catch(e) { return; }

  var errorHandler = function(e){ e.preventDefault(); e.stopImmediatePropagation(); };
  open.onabort = open.onerror = errorHandler;
  open.onupgradeneeded = function(upgradeEvent) {
    upgradeEvent.target.transaction.abort();
  };

  open.onsuccess = function(openEvent) {
    var db = openEvent.target.result;
    db.onerror = db.onabort = errorHandler;

    try {
      var store = db.transaction('FILE_DATA', 'readwrite').objectStore('FILE_DATA');
      store.openCursor().onsuccess = function(cursorEvent) {
        var cursor = cursorEvent.target.result;
        if (cursor) {
          if (cursor.key.indexOf('/UnityCache/Shared/') !== -1) cursor.delete();
          cursor.continue();
        }
      };
    } catch(e) {}

    db.close();
  };
})();
您还可能需要修改您的CORS配置,从而公开ETag头,以及允许通过CachedXMLHttpRequest加载的任何资源的头部HTTP请求。
[AppleScript] 纯文本查看 复制代码
window.addEventListener('error', function(e){
  if (e.message.indexOf('InvalidStateError') !== -1) {
    e.stopImmediatePropagation();
  }
}, false);
在使用CachedXMLHttpRequest时需要注意的一点是,所有GET请求的请求都会在默认情况下被缓存。如果您在查询字符串中使用缓存克星或时间戳来生成请求,这可能会有问题。这个类的Kongregate版本允许您配置一个黑名单,以防止在需要时对资源进行缓存。

WebAudio内存使用
另一个需要注意的重要事情是,你的游戏所播放的音频存储在未压缩的内存中。根据您的使用情况,这可能导致内存使用量的巨大峰值。
同样,Unity团队在商店中也有一个资源来帮助解决这个问题。不幸的是,当前的解决方案在循环音频中存在一些问题,因此对音乐可能没有太大的帮助,因为音乐很可能是大型音频文件的主要来源。

1
首存1元送彩金的博彩_首存一元送彩金38博彩_首存1元送彩金论坛