背景
Unityで作成したhtmlをWebに公開したいので、試しにローカルのApacheコンテナで実行できるようにした。
UnityでWebGLビルドしたhtmlは、ホスティングしないでChromeで開くとエラーになる。
TL;DR
- Unityでビルドしたgz圧縮のWebGLファイルをApacheコンテナで実行
- Unity公式ドキュメントに従って、WebGLを利用するためのサーバ設定を.htaccessに記述
- Apacheコンテナのデフォルト設定では、htdocs配下がAllowOverride Noneになっており、.htaccessが無効なので注意が必要
前提
Ver
Unity 2021.2.7f1 personal
Docker Engine 20.10.11
Chrome 98.0.4758.80(Official Build) (arm64)
WebGLの圧縮形式
Brotli圧縮(拡張子は.br)は圧縮率が向上していながら、圧縮/伸長速度は同程度を維持しているなどメリットがあるが、SSL/TLSが必須となっているため、今回のローカル実行でのお試しはgz圧縮で実施。
Unityでの設定は Edit → ProjectSetttings → Playerで WebGLタブを選択して、Cpmpression FormatでGzipを選択する。
手順
1. UnityでWebGL形式ビルド
Unityでゲームを作成してWebGL形式でビルドする。
Unityによるゲーム作成は Unityの教科書 がとても参考になるのでおすすめ。
2. Apacheの起動
ここではhtmlを配置せずにApacheのコンテナを試しに起動するまで。
2.1 Apacheコンテナの起動
Docker Desktopなどがインストールされ、Docker Engineがインストールされている前提。
Apacheのコンテナイメージを取得して、起動する。
% docker pull httpd
Using default tag: latest
・・・略
% docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 1c2ff9e4eb7d 3 days ago 136MB
% docker run -d -p 8080:80 httpd
Chromeで localhost:8080 にアクセスして It Woks! が表示されることを確認する。
起動を確認したら、docker ps でコンテナIDを調べて、 docker stop と docker rm の引数にコンテナIDを指定して実行して、コンテナを削除する。
3 WebGLファイルと.htaccessの配置
Apacheコンテナに対してUnityでビルドしたWebGLを配置しChromeでゲームができるようにする。
3.1 htdocsの作成とWebGLファイルの配置
ローカルPCの適当なディレクトリに htdocsを作成する。
ビルドしたWebGLファイル一式をhtdocs配下に配置する。
3.2 .htaccessファイルの配置
3.1 で作成した htdocs/Build 直下 .htaccessファイルを配置する。
Unity公式ドキュメントに記載された圧縮形式によるWebGL対応の手順を試しているだけで、.htaccessの使用を推奨しているわけではない。
.htaccessファイルの中身はUnity公式ドキュメントを参照して作成する。
https://docs.unity3d.com/ja/2021.2/Manual/webgl-server-configuration-code-samples.html
拡張子brの部分はBrotli圧縮を使用しないので、コメントしているが、そのままでも問題なし。
AddEncoding gzip .unityweb の部分はgzip圧縮のローディングパフォーマンスが改善するとあるのでコメントアウトを実施。
# This configuration file should be uploaded to the server as "<Application Folder>/Build/.htaccess"
# NOTE: "mod_mime" Apache module must be enabled for this configuration to work.
# <IfModule mod_mime.c>
# The following lines are required for builds without decompression fallback, compressed with gzip
RemoveType .gz
AddEncoding gzip .gz
AddType application/octet-stream .data.gz
AddType application/wasm .wasm.gz
AddType application/javascript .js.gz
AddType application/octet-stream .symbols.json.gz
# The following lines are required for builds without decompression fallback, compressed with Brotli
# RemoveType .br
# RemoveLanguage .br
# AddEncoding br .br
# AddType application/octet-stream .data.br
# AddType application/wasm .wasm.br
# AddType application/javascript .js.br
# AddType application/octet-stream .symbols.json.br
# The following line improves loading performance for uncompressed builds
AddType application/wasm .wasm
# Uncomment the following line to improve loading performance for gzip-compressed builds with decompression fallback
AddEncoding gzip .unityweb
# Uncomment the following line to improve loading performance for brotli-compressed builds with decompression fallback
# AddEncoding br .unityweb
3.3 作成したhtdocsディレクトリをマウントして起動
3.1と3.2 で作成したhtdocsディレクトリをマウントしてdockerを起動する。
% docker run -d -p 8080:80 -v [適当なディレクトリ]/htdocs:/usr/local/apache2/htdocs httpd
4 エラーのデバッグ
4.1 Build/XXXX_WebGL.framework.js.gzのエラー
この状態でChromeで localhost:8080 にアクセスして起動確認をすると以下のようなエラーがブラウザに表示される。
Unable to parse Build/XXXX_WebGL.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.
3.1 で htdocs に配置した "Build/XXXX_WebGL.framework.js.gz を解析できません。" というエラーが表示されている。そして最後の行に "ブラウザの[コンソール]と[Devtoolsネットワーク]タブを確認してデバッグします。" ということが書かれている。
4.2 Chromeのデベロッパーツールによるデバッグ
エラーメッセージに書かれている通り、デベロッパーツールでネットワークタブを見ると、XXXX_WebGL.framework.js.gz の Responseヘッダーにある Content-typeがapplication/x-gzipになっている。
3.2 で指定した "AddType application/javascript .js.gz" が効いてなくて、.js.gzの拡張子が jsファイルとして解釈されていない。
4.3 httpd.confの確認
.htaccessを有効にするためには、 対象のディレクトリに対して、 "AllowOverride All" の設定が必要だ。
以下のコマンドでコンテナにSSHして、Apacheの httpd.conf の中身を確認する。
% docker exec -it [コンテナID] /bin/bash
# httpd.conf に対して AllowOverride でgrepして、行のあたりをつけてから中身を確認
% root@[コンテナID]:/usr/local/apache2# cat conf/httpd.conf | grep AllowOverride -n
249: AllowOverride none
282: # AllowOverride controls what directives may be placed in .htaccess files.
284: # AllowOverride FileInfo AuthConfig Limit
286: AllowOverride None
399: AllowOverride None
root@[コンテナID]:/usr/local/apache2# cat conf/httpd.conf -n
260 #
261 # DocumentRoot: The directory out of which you will serve your
262 # documents. By default, all requests are taken from this directory, but
263 # symbolic links and aliases may be used to point to other locations.
264 #
265 DocumentRoot "/usr/local/apache2/htdocs"
266 <Directory "/usr/local/apache2/htdocs">
267 #
268 # Possible values for the Options directive are "None", "All",
269 # or any combination of:
270 # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
271 #
272 # Note that "MultiViews" must be named *explicitly* --- "Options All"
273 # doesn't give it to you.
274 #
275 # The Options directive is both complicated and important. Please see
276 # http://httpd.apache.org/docs/2.4/mod/core.html#options
277 # for more information.
278 #
279 Options Indexes FollowSymLinks
280
281 #
282 # AllowOverride controls what directives may be placed in .htaccess files.
283 # It can be "All", "None", or any combination of the keywords:
284 # AllowOverride FileInfo AuthConfig Limit
285 #
286 AllowOverride None
287
288 #
289 # Controls who can get stuff from this server.
290 #
291 Require all granted
292 </Directory>
やはり "/usr/local/apache2/htdocs" に対して"AllowOverride None"(286行目) になっている。
5 httpd.confの修正
コンテナのhttpd.confは直接編集できないので、ローカルにいったん取得して、修正してマウントして起動する。
5.1 コンテナのhttpd.confをローカルに取得
docker run --rm httpd cat /usr/local/apache2/conf/httpd.conf > conf/httpd.conf
ローカルに取得したファイルに対して、"AllowOverride None"(286行目)を"AllowOverride All"に変更
5.2 httpd.confもマウントしてコンテナを起動
起動していたApacheコンテナを削除してhttpd.confもマウントに追加して起動する。
docker run -d -p 8080:80 -v [適当なディレクトリ]/htdocs:/usr/local/apache2/htdocs -v [適当なディレクトリ2]/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf httpd
5.3 Chromeで確認
まだエラーが出る場合はキャッシュが残っている可能性あり。
Chrome右上の設定 → セキュリティとプライバシー → 閲覧履歴データの削除でCookieやキャッシュされた画像とファイルなどを削除する。
以上
感想
- 普段Apacheを触ってないのに、Webサーバを立てようとするからこういうことになる
- 設定の中身を大して理解せずに、とりあえずエラーメッセージでググったせいで、数時間を無駄に費やした
- UnityのWebGLビルドのエラーメッセージ通りにデバッグすればすぐに解決できた
- 英語のエラーメッセージも軽く読み流す悪いクセが出た