Unity の Web ビルドを、自分のサーバーに置いて公開しました。unityroom や itch.io に上げるのではなく、自分のドメインで配る形です。
やってみて分かったのは、これでした。
必要な設定は、ほぼ「圧縮済みファイルに正しいヘッダーを返すこと」だけ。
Caddy なら10行ほどです。ただし、そこを外すとブラウザは無言で読み込みに失敗します。
この記事の前提
Unity 6.6(6000.6.0f1)の WebGL ビルド(圧縮は Brotli、Decompression Fallback なし)を、Docker 上の Caddy で配信しました。前段にも Caddy(TLS 終端)がいる2段構成です。確認日は2026年9月16日。
構成
手順 01
ブラウザ
手順 02
前段の Caddy
TLS・HSTS・gzip/zstd
手順 03
サービスの Caddy
静的配信・ヘッダー付与
手順 04
ビルドのファイル
アップロードで置くだけ
ゲームのビルドは git に入れていません。約10MB あり、ビルドのたびに中身が変わるからです。サーバーの公開用フォルダに置いて、Caddy から静的に配るだけにしています。
肝心の設定(これだけ)
# /play/<ゲーム> → /play/<ゲーム>/(handle_path の前に置く)
@gameNoSlash path_regexp gameNoSlash ^/play/([a-z0-9-]+)$
redir @gameNoSlash /play/{re.gameNoSlash.1}/ 308
handle_path /play/* {
root * /srv/games
@br path *.br
header @br Content-Encoding br
@wasm path *.wasm *.wasm.br
header @wasm Content-Type application/wasm
@js path *.js.br
header @js Content-Type application/javascript
@data path *.data *.data.br
header @data Content-Type application/octet-stream
header Cache-Control "no-cache"
file_server
}
ポイントは3つです。
- 1
.br には Content-Encoding: br を付ける
Unity の Brotli ビルドはWebGL.wasm.brのような圧縮済みファイルを出す。サーバーが「圧縮されている」と伝えないと、ブラウザはただのバイナリとして受け取って失敗する - 2
中身に合った Content-Type も付ける
.wasm.brは放っておくとapplication/octet-streamになる。application/wasmを返さないと、高速な読み込み経路(ストリーミングコンパイル)が使えない - 3
末尾スラッシュのリダイレクトは handle_path の外に置く
handle_pathの中では接頭辞/playが外れているので、中に書くと接頭辞の落ちた URL に飛ぶ
実測したヘッダー
| パス | 結果 |
|---|---|
/play/breakout | 308 → /play/breakout/ |
…/Build/WebGL.wasm.br | 200・Content-Encoding: br・Content-Type: application/wasm |
…/Build/WebGL.data.br | br・application/octet-stream |
…/Build/WebGL.framework.js.br | br・application/javascript |
…/Build/WebGL.loader.js | gzip(前段の Caddy が圧縮)・text/javascript |
分かったこと。
file_serverは、先にheaderで入れたContent-Typeを上書きしませんでした。 期待どおりの動きです- 前段の Caddy に
encode gzip zstdがあっても、すでにContent-Encoding: brが付いた応答は二重に圧縮されませんでした
⚠️ ヘッダーを付けられないサーバーなら、ビルド設定を変える
共有レンタルサーバーなどで応答ヘッダーを触れない場合、この方法は使えません。その場合は Unity 側の Publishing Settings で Decompression Fallback を有効にしてビルドします。読み込みは遅くなりますが、サーバーの設定なしで動きます。
設定ファイルはフォルダごとマウントする
Docker で Caddy を動かすとき、最初は Caddyfile を1ファイルだけマウントしていました。
ファイル1つをマウント
volumes: - ./Caddyfile:/etc/caddy/Caddyfileデプロイで
git checkout -f がファイルを作り直すと、コンテナは古い中身を見続ける(ファイルの実体が置き換わるため)フォルダごとマウント
volumes: - ./caddy:/etc/caddy作り直されても新しい中身が見える
反映にかかった時間
1秒
ビルドのアップロード
約10MB を tar でまるごと
8秒
デプロイ
設定の検証〜外形確認まで
11.6MiB
配信コンテナのメモリ
起動直後
64MiB
メモリの上限
静的配信ならこれで足りる
アップロードは tar で固めてそのまま展開する形にしています。差分同期ではなく毎回まるごと置き換えですが、10MB 程度ならこのほうが事故が少ないです。
サイズの話
公開した時点では、WebGL.wasm.br が 7.3MB(展開すると 38.3MB)、全体で約 10.1MB ありました。スマホの回線では重いので、このあと削っています。
検索に出す/出さないの整理
ゲーム本体のページ(/play/…)は X-Robots-Tag: noindex を付けて検索に出していません。中身は Unity が生成した HTML で、説明も見出しもないからです。検索に出すのは、制作の記録を書いた紹介ページのほうにしています。
代わりに、ゲームを直接開いた人のために、上部に戻る帯を差し込んでいます。ビルドのたびに index.html は作り直されるので、アップロードのスクリプトの中で毎回差し込む形にしました。
このゲームを作った過程はブロック崩しのページに、環境まわりで踏んだ問題はWindowsの落とし穴14個にあります。