Unity for WebGL Gzip,Brotli圧縮ビルドアプリの実行

Unity で作成した WebGL アプリケーション(圧縮ビルド)を試そうとした際に Httpサーバの設定をしておらず、Content-Encoding などのエラーが発生したのでその対処方法。

環境

Unity 2021.1.25f1
Windows10 pro 64bit
Apache2.4
Google Chrome バージョン: 95.0.4638.54(Official Build) (64 ビット)

発生したエラー、ワーニング

Unable to parse Build/build.framework.js.gz! This can happen if build compression was enabled but web server hosting the content was misconfigured to not serve the file with HTTP Response Header "Content-Encoding: gzip" present. Check browser Console and Devtools Network tab to debug.

HTTP Response Header "Content-Type" configured incorrectly on the server for file Build/build.wasm.gz , should be "application/wasm". Startup time performance will suffer.

原因

Unity で WebGL アプリケーションをビルドすると index.html と各種データが生成される。
その中の Build フォルダ内のデータの一部はビルド時に指定されている型式で圧縮されたものになっており「 webgl-app-test 」という名前でビルドした場合は次のようになっている。

圧縮なしGzipBrotli
webgl-app-test.datawebgl-app-test.data.gzwebgl-app-test.data.br
webgl-app-test.framework.jswebgl-app-test.framework.js.gz webgl-app-test.framework.js.br
webgl-app-test.wasmwebgl-app-test.wasm.gzwebgl-app-test.wasm.br

index.html を読み込んだブラウザからはその中で参照されているファイルを追加でサーバーに対し GETリクエストしてくるが上記のファイル名でリクエストが来るため各ファイル(拡張子)の Content-Type、Content-Encoding を正しく返すように設定する必要がある。

Unityマニュアルにも書いてある
https://docs.unity3d.com/ja/2021.1/Manual/webgl-deploying.html の下記項目

Unity User Manual 2021.1
 プラットフォーム開発
  WebGL
   WebGL での開発を始めるにあたって
    WebGL: Compressed builds and server configuratio

マニュアルより抜粋

Compression methodFile extensionResponse header
gzip.gzContent-Encoding: gzip
Brotli.brContent-Encoding: br
Content-Encoding headers
File extensionResponse header
.wasm, .wasm.gz, .wasm.brContent-Type: application/wasm
WebAssembly streaming (higher level header)
File extensionResponse header
.js, .js.gz, js.brContent-Type: application/javascript
Additional headers

対応

というわけで .htaccess や .conf などでマニュアル通りに Mime Type の設定を行うことでとりあえず解決した。

AddType application/wasm wasm
AddType application/octet-streamt data
AddType application/javascript js

<FilesMatch "(\.js.gz)$">
	Header set Content-Encoding gzip
	Header set Content-Type application/javascript
	Header append Vary Accept-Encoding
</FilesMatch>
<FilesMatch "(\.data.gz)$">
	Header set Content-Encoding gzip
	Header set Content-Type application/octet-streamt
	Header append Vary Accept-Encoding
</FilesMatch>
<FilesMatch "(\.wasm.gz)$">
	Header set Content-Encoding gzip
	Header set Content-Type application/wasm
	Header append Vary Accept-Encoding
</FilesMatch>

<FilesMatch "(\.js.br)$">
	Header set Content-Encoding br
	Header set Content-Type application/javascript
	Header append Vary Accept-Encoding
</FilesMatch>
<FilesMatch "(\.data.br)$">
	Header set Content-Encoding br
	Header set Content-Type application/octet-streamt
	Header append Vary Accept-Encoding
</FilesMatch>
<FilesMatch "(\.wasm.br)$">
	Header set Content-Encoding br
	Header set Content-Type application/wasm
	Header append Vary Accept-Encoding
</FilesMatch>

ただしこの方法では拡張子により強制的に Content-Encoding を設定しているため、圧縮データに対応していないブラウザからアクセスされた場合は動作しない可能性がある。

必要があれば、RewriteRule の設定などで圧縮形式に非対応ブラウザからのアクセスの際は圧縮なし版へリダイレクト、またはエラー画面にするなどを行うとよいかもしれない。

Brotli圧縮のサンプル

Brotli圧縮非対応、WebGLを動作させない設定になっているブラウザからでは動作しないと思う。

その他

unity-webgl-data-caching

ビルド時の Data Caching が有効だったり、サーバの設定でキャッシュされるようになっているとテスト中に動作しなくなったりした場合があるのでテスト中は .htaccess でキャッシュを強制的に無効にするなどするといいかもしれない。

テストした際は xxx.data.br がキャッシュされていたので .htaccess に下記のように設定を追加していた。

<Files ~ "\.(data.br)$">
Header add Pragma "no-cache"
Header set Cache-Control no-cache
</Files>