Unity: WebGL解析构建的压缩包

3,125 阅读5分钟

最近在用Unity打WebGL包,运行时出现无法解析压缩包的情况,如图:

image.png

根据上图的提示,我们也可以看出是托管的Web服务器没有设置Content-Encoding.gzip响应头,导致浏览器无法正确解析和加载该文件。之所以会出现这个问题,是unity在打包WebGL包时,构建设置中默认开启了Gzip压缩方式:

image.png

要解决这个问题有三种方式:

禁用压缩

通过将Compression Format选项设置成Disabled

image.png

这是最简单的方式,但禁用压缩后,会导致导出的WebGL包体变大,有时会超过压缩后包体的一倍以上,大型游戏情况更甚,对于H5游戏,这将导致很多问题,比如:

  • 下载时间延长:较大的包体会增加游戏的下载时间。用户可能需要等待更长时间才能开始游戏,特别是在网络条件较差的情况下。这可能导致用户流失或不愿意等待。
  • 用户流量消耗增加:大型包体需要更多的数据传输,因此用户在下载和玩游戏时可能会使用更多的移动数据流量。这可能对用户有一定的成本影响,并可能限制某些用户在移动网络环境下的游戏体验。
  • 设备存储空间占用增加:较大的包体需要更多的存储空间来安装和保存游戏文件。如果用户的设备存储空间有限,他们可能会在下载或安装游戏时遇到问题,并可能选择删除或不安装包体较大的游戏。
  • 用户留存率降低:对于移动设备上的H5游戏来说,用户通常更倾向于玩轻量级、快速下载和加载的游戏。如果包体过大,可能会导致用户流失率增加,因为他们可能更倾向于寻找更小的游戏来满足他们的需求。
  • 游戏性能下降:较大的包体可能会对游戏性能产生影响,特别是在低端设备上。加载和解析大型资源文件可能导致卡顿、延迟或性能下降的问题。这可能会影响游戏的流畅性和用户体验。

因此这个方案只针对那些资源比较少的游戏。

设置Content-Encoding响应头

从最上面的图中,我们已经知道可以通过设置响应头来解决这个问题,在这之前,先说下unity的压缩方式,unity目前提供了两种方式的压缩方式gzipBrotli

压缩方法描述
gzip这是默认选项。gzip 文件比 Brotli 文件更大,但构建速度更快,且所有浏览器都基于 HTTP 和 HTTPS 实现此格式的本机支持。
BrotliBrotli 压缩提供最佳压缩比。Brotli 压缩文件小于 gzip,但需要更长的压缩时间,因此会增加发布版本的迭代时间。Chrome 和 Firefox 仅原生支持基于 HTTPS 的 Brotli 压缩。
Disabled禁用压缩。如果要在后期处理脚本中实现您自己的压缩,请使用此选项。如果计划在托管服务器上使用静态压缩,也应该使用此选项。

因此,您可能需要调整服务器配置以匹配特定构建设置。具体而言,如果已使用其他服务器端配置来压缩托管的文件(这可能会干扰此设置),可能会出现问题。 为了使浏览器在下载应用程序期间以原生方式执行解压缩,需要在服务器响应中附加一个 Content-Encoding 标头。该标头必须与 Unity 在构建时使用的压缩类型相对应,

  • Gzip方式 响应头:Content-Encoding gzip
  • Brotli方式 响应头:Content-Encoding br

这里用Nginx配置来举例:

Server configuration for WebGL builds (Nginx)

http {
# ...

server {
# Add the following config within http server configuration
# ...
 
# On-disk Brotli-precompressed data files should be served with compression enabled:
location ~ .+.(data|symbols.json).br$ {
    # Because this file is already pre-compressed on disk, disable the on-demand compression on it.
    # Otherwise nginx would attempt double compression.
    gzip off;
    add_header Content-Encoding br;
    default_type application/octet-stream;
}

# On-disk Brotli-precompressed JavaScript code files:
location ~ .+.js.br$ {
    gzip off; # Do not attempt dynamic gzip compression on an already compressed file
    add_header Content-Encoding br;
    default_type application/javascript;
}

# On-disk Brotli-precompressed WebAssembly files:
location ~ .+.wasm.br$ {
    gzip off; # Do not attempt dynamic gzip compression on an already compressed file
    add_header Content-Encoding br;
    # Enable streaming WebAssembly compilation by specifying the correct MIME type for
    # Wasm files.
    default_type application/wasm;
}

# On-disk gzip-precompressed data files should be served with compression enabled:
location ~ .+.(data|symbols.json).gz$ {
    gzip off; # Do not attempt dynamic gzip compression on an already compressed file
    add_header Content-Encoding gzip;
    default_type application/octet-stream;
}

# On-disk gzip-precompressed JavaScript code files:
location ~ .+.js.gz$ {
    gzip off; # Do not attempt dynamic gzip compression on an already compressed file
    add_header Content-Encoding gzip;
    default_type application/javascript;
}

# On-disk gzip-precompressed WebAssembly files:
location ~ .+.wasm.gz$ {
    gzip off; # Do not attempt dynamic gzip compression on an already compressed file
    add_header Content-Encoding gzip;
    # Enable streaming WebAssembly compilation by specifying the correct MIME type for
    # Wasm files.
    default_type application/wasm;
}
}
}

Decompression Fallback(解压缩回退)

如果你无法设置服务器的响应头,比如你上线到其他H5游戏平台,而他们的服务器没有设置对应的响应头,并且你也不想禁用压缩增大包体,unity还提供了一种 解压缩回退的方式Decompression Fallback

Decompression Fallback选项使 Unity 能够自动将 JavaScript 解压缩器嵌入到您的构建中。该解压缩器与您选择的压缩方法相对应,它在浏览器无法解压缩内容时执行解压缩。

启用解压缩回退

从 Player Settings 窗口启用解压缩回退(菜单:Edit > Project Settings > Player,然后选择 WebGL 并展开 Publishing Settings 部分):

image.png

如果启用解压缩回退,Unity 会向构建文件添加一个 .unityweb 扩展名。默认情况下,Decompression Fallback 选项处于禁用状态,因为使用此选项会导致加载器大小增大和构建文件加载方案的效率降低,会增加游戏加载的时间,但大部分情况下,相比于禁用压缩,还是比较推荐用这种方式。

上面三种方式,每种方式都有优缺点,因此具体使用哪一种,需要根据具体的项目的情况去权衡。