INDIE INDEX

レベル:実践

Webに書き出す|UnityとGodotの制限とサーバー設定

公開 2026-10-24更新 2026-10-24

Godot 4 の C# のプロジェクトは今のところ Web に書き出せず、Unity では C# のスレッドが使えません。サーバーでは、Unity はブラウザに展開させる設定のとき圧縮の形式に合わせた Content-Encoding を付け、Godot は Use Threads で書き出したときだけ、安全なコンテキストで Cross-Origin-Opener-Policy と Cross-Origin-Embedder-Policy を付けます。

このページの目次
  1. Web で動く条件
  2. Web で使えないもの・限られるもの
  3. Godot のスレッドと配信のヘッダー
  4. Unity の圧縮の設定と配信のヘッダー
  5. 書き出したあとに確かめる手順
  6. 設定と、必要なものを図で見る
  7. 失敗を避ける注意
  8. 次に読む
  9. 情報源

Web で動く条件

Web で動く条件には、たとえば次のものがあります。

Web で動く条件

エンジン項目内容
Godot描画・モバイルGodot 4 が対象にできるのは、WebGL(グラフィックスの API)の 2.0 だけで、描画方式は Compatibility です。Forward+ と Mobile は Web では使えません。Godot は今のところ WebGPU に対応していません。Safari の WebGL 2.0 への対応には、ほかのブラウザに無い問題がいくつかあります。Web への書き出しはモバイルでも動かせますが、いくつかの注意があります。
Unityブラウザと描画WebGL 2 に対応し、HTML 5 の標準に沿い、64 ビットで WebAssembly(ブラウザで Unity のコードを動かすためのバイトコードの形式)に対応しているという条件を満たすブラウザに対応しています。デスクトップでは、Google Chrome(Windows・macOS・Linux)、Mozilla Firefox(Windows・macOS・Linux)、Apple Safari(macOS)、Microsoft Edge(Windows・macOS・Linux)に対応していて、Edge は Chromium ベースの最新版にも対応しています。Safari 15 より前の版は WebGL 2 に対応していません。Safari は、iFrame の中で動くコンテンツでは IndexedDB に対応していません。Linux では、Advanced Audio Coding(AAC)コーデックの対応を、パッケージマネージャー(たとえば GStreamer のパッケージ)で入れる必要が出ることがあります。Web の WebGL のグラフィックス API は OpenGL ES の機能に基づいていて、Web ではそれによる制限があります。
UnityモバイルのブラウザiOS の Safari 15 以降と、Android の Chrome 58 以降に対応しています。古い版では、性能に影響する問題が出たり、Unity のコンテンツが動かなかったりすることがあります。モバイルでは、モバイルのブラウザで動かす、WebView でネイティブアプリに埋め込む、Progressive Web App(PWA)のテンプレートを使う、という方法があります。
表1

Web で使えないもの・限られるもの

エンジンごとに、Web で使えないものや限られるものには、たとえば次のものがあります。

Web で使えないもの・限られるもの

エンジン分野内容
GodotC#・保存・バックグラウンドGodot 4 の C# のプロジェクトは、今のところ Web に書き出せません。`user://` のファイルシステムを永続させたいときは、遊ぶ人が Cookie(具体的には IndexedDB)を許可している必要があります。iframe に入れたゲームを遊ぶときは、サードパーティの Cookie も有効である必要があります。シークレットやプライベートのブラウズのモードでも、永続しません。`OS.is_userfs_persistent()` は `user://` が永続かどうかを調べる関数で、場合によっては誤った肯定の結果を返すことがあります。タブがアクティブでなくなると、ブラウザがプロジェクトを一時停止し、`_process()` や `_physics_process()` のような関数は、タブがアクティブに戻るまで動きません。長いあいだタブを切り替えると、通信するゲームが切断されることがあります。この制限は、フォーカスの外れたブラウザのウィンドウには当てはまらないため、遊ぶ人の側では、別のタブでなく別のウィンドウでプロジェクトを動かす方法があります。
Godot全画面・クリップボード・ゲームパッド・マイクブラウザは、任意のタイミングで全画面にすることも、カーソルを取り込むことも許しません。どちらも、JavaScript の入力イベントへの応答として行う必要があります。Godot では、`_input` や `_unhandled_input` のような、押された入力イベントのコールバックの中で全画面にします。Input のシングルトンへの問い合わせでは足りません。プロジェクト設定の全画面は、エンジンが有効な入力イベントのハンドラの中から始まらないと効きません。これには HTML ページのカスタマイズが要ります。エンジンと OS のクリップボードの同期には、Clipboard API に対応したブラウザが要ります。非同期の仕組みのため、GDScript から使うと確実でないことがあり、安全なコンテキストが要ります。ゲームパッドは、ボタンのどれかが押されるまで検出されません。ブラウザ・OS・ゲームパッドの組み合わせによっては、割り当てが違うことがあり、こちらも安全なコンテキストが要ります。マイクへのアクセスにも、安全なコンテキストが要ります。
Godot音一部のブラウザは、ウェブサイトでの音の自動再生を制限しています。Godot 4.3 からは、Web では Web Audio API を使う Sample の再生モードが既定です。このモードでは、AudioEffect・残響とドップラー効果・プロシージャルな音の生成に対応せず、位置による音は、ノードのプロパティによっては正しく動かないことがあります。`Audio > General > Default Playback Type.web` のプロジェクト設定か、AudioStreamPlayer などのノードの Playback Type を Stream にすると、Godot 自身の音の再生に変わります。遅延は(スレッドを無効にしているときは特に)増えますが、Godot の音の機能の全体が使えます。
Godotネットワーク低レベルの通信は、ブラウザが対応していないため実装されていません。今のところ対応しているのは、HTTP client・HTTP requests・WebSocket(クライアント)・WebRTC だけです。HTTP のクラスには、StreamPeer へのアクセスや変更ができない、スレッドを使う・ブロックするモードが使えない、1フレームに1回より多くは進められないためループでポーリングすると固まる、チャンクの返事が使えない、ホストの検証を無効にできない、同一オリジンポリシーの対象になる、という制限もあります。
UnityC# のスレッドとコードの動的な生成WebAssembly にはマルチスレッドのガベージコレクションが無いため、C# のスレッドは使えません。`System.Threading` の名前空間のものは使えず、たとえば `System.Threading.Timer` は Web のビルドでは動かず、`CancellationTokenSource` に指定したタイムアウトも、実際には切れません。ネイティブの C/C++ のスレッドは、実験的な Player の設定 Native C/C++ Multithreading を有効にした場合だけ、一部使えます。Web は AOT のプラットフォームのため、`System.Reflection.Emit` によるコードの動的な生成もできません。
Unityネットワークブラウザが IP ソケットへの直接のアクセスを許さないため、`System.Net.Sockets`・`System.Net.Http`・`System.Net.WebSockets` などの .NET のネットワークのクラスと、`UnityEngine.Ping`(ICMP)は使えません。`UnityWebRequest` はブラウザの Fetch API を使うため、別のサーバーの資源にアクセスするときは、アクセス先のサーバーが CORS で許可している必要があります。TCP や UDP のソケットの代わりには、Web に対応した Unity Netcode のパッケージを使えます。
Unity音・物理・デバッグ・キャッシュ・キーボードWeb Audio API を土台にした独自のバックエンドを使い、基本の音の機能だけに対応します。ブラウザは、遊ぶ人がマウスのクリック・タッチ・キー入力でページを操作するまで、音の再生を許しません。Web の物理のシミュレーションは、Editor や他のプラットフォームと同じ結果になることが保証されていません。WebAssembly は浮動小数点の計算を常に完全な精度で行い、他のプラットフォームは極小の数をゼロにする設定で動かすためです。Visual Studio での Web のビルドのデバッグには対応していません。ブラウザのファイルシステムへのアクセスが制限されているため、Unity Cache と Caching の Scripting API には対応せず、アセットデータと AssetBundle へのネットワークのリクエストは、ブラウザのキャッシュに入ります。Input System の、物理キーと実際のキーボード配列の対応づけにも対応していないため、英語以外のキーボードでは、一部の `InputControl` のプロパティが想定どおりに動きません。
表2

Godot のスレッドと配信のヘッダー

Godot の Web 書き出しのスレッドと配信には、たとえば次の項目があります。

Godot のスレッドと配信のヘッダー

項目内容
1 スレッドの書き出しと Thread Support(Use Threads)Godot 4.3 から、1 スレッドでの書き出しに対応しています。これが今の Web への書き出しの既定の方法です。スレッドは使えません。複数のスレッドを使う書き出しには、特定のサーバー側のヘッダーと、完全な cross-origin isolation(広告やサードパーティの連携を、ゲームを置くウェブサイトに置けないということ)が要ります。Thread Support を有効にすると、書き出したプロジェクトでマルチスレッドを使えます。Sample でなく Stream の再生モードにしたときの、低遅延の音の再生にも使われます。
SharedArrayBuffer・安全なコンテキスト・ヘッダーUse Threads で書き出したときだけ、Godot 4 の Web の書き出しは SharedArrayBuffer を使います。これには安全なコンテキストが要ります。ブラウザの機能は、ウェブページが安全な HTTPS の接続で配られたときだけ使えるものが増えています。localhost は、ふつうこの条件の対象外です。ファイルを配るときには、Cross-Origin-Opener-Policy に same-origin を、Cross-Origin-Embedder-Policy に require-corp を入れたヘッダーを付ける必要があります。クライアントがこのヘッダーを受け取らず、次の行のサービスワーカーの仕組みも使っていないと、プロジェクトは動きません。
PWA(Progressive Web App > Enable)サーバーを自分で制御できない場合や、レスポンスのヘッダーを足せない場合のために、チェックを入れると、サービスワーカーを使った方法で、これらのヘッダーがあるように見せかけ、プロジェクトを動かせます。この場合も安全なコンテキストは要ります。サーバーがこのヘッダーを送っていなくても、cross-origin isolation のヘッダーが常にある状態にでき、Enable Cross Origin Isolation Headers のチェックを外すと、この動きをやめられます。PWA を有効にすると、一度読み込んだあとは、インターネットに繋がらなくても読み込めるようにもなります。ただし、ブラウザは、遊ぶ人のディスクの空きが少なくなったときか、遊ぶ人がしばらくプロジェクトを開いていないときに、キャッシュしたデータを消すことがあります。
Extensions Support有効にすると GDExtension を読み込めます。GDExtension は、Web 向けに別途コンパイルされている必要があります。スレッドと同じく、有効にするには cross-origin isolation のヘッダーが要ります。
ファイル・MIME タイプ・サーバー側の圧縮`.html` は表示用の既定の HTML ページ、`.wasm` はエンジンを実装した WebAssembly のモジュール、`.pck` は Godot のメインのパックでゲームが入っていて、`.js` は起動のコードで、`.png` は起動時のスプラッシュ画像です。`.html` 以外のファイルは、名前を変えずに `.html` の隣に置きます。`.wasm` は `application/wasm` で配られ、`.pck` は、ふつう `application/octet-stream` で配られます。`.wasm` を `application/wasm` 以外の MIME タイプで配ると、起動時の最適化の一部が働かないことがあります。GitHub Pages は、その場での圧縮(gzip)を提供しています。itch.io と GitLab Pages は、その場での圧縮を提供していません(GitLab Pages は、手動の gzip の事前圧縮に対応しています)。`.wasm` は、gzip で圧縮すると、元の大きさの約4分の1まで小さくなります。
表3

GDExtension とは

GDExtension は、エンジンの機能を広げることができる共有ライブラリを表すリソースの種類です。GDExtension 自体はスクリプト言語ではなく、GDScript のリソースとは関係がありません。

Unity の圧縮の設定と配信のヘッダー

Unity の Web のビルドで、サーバーの設定に影響する主な設定は、Compression Format と Decompression Fallback です。表には、この設定と、それに関わるヘッダーを並べます。

Unity の圧縮の設定と配信のヘッダー

項目内容
Compression FormatEdit > Project Settings > Player で Web を選び、Publishing Settings の節を開いて選びます。gzip は既定で、Brotli よりファイルは大きいものの、ビルドが速く、すべてのブラウザが HTTP でも HTTPS でもネイティブに対応しています。Brotli は圧縮の比率が最も高く、gzip よりファイルは小さいものの、圧縮に時間がかかり、リリースビルドの試行の時間が延びます。Chrome と Firefox は、Brotli に HTTPS でだけネイティブに対応しています。Disabled は圧縮をしません。ビルド後の処理で独自の圧縮をしたいときと、ホスティングのサーバーで静的圧縮を使う予定のときの選択肢です。この設定が効くのはリリースビルドだけで、Development ビルドは圧縮されません。
Decompression Fallback既定は無効です。無効のとき、ビルドのファイルには、選んだ圧縮に対応した拡張子(gzip は `.gz`、Brotli は `.br`)が付きます。ブラウザにファイルをダウンロード中にネイティブに展開させるには、適切な HTTP のヘッダーを付けて、サーバーから圧縮したファイルを配ります。ネイティブな展開は、JavaScript による展開のフォールバックより速く、アプリの起動の時間を短くできることがあります。有効のとき、Unity が、選んだ圧縮に合う JavaScript の展開の仕組みをビルドに埋め込み、ブラウザが展開に失敗したときに、その仕組みが内容を展開します。ビルドのファイルには `.unityweb` の拡張子が付きます。ローダーの大きさが大きくなり、ビルドのファイルの読み込みの仕組みは、効率が下がります。
Content-Encodingブラウザに圧縮の種類を伝えるヘッダーで、ブラウザが圧縮したファイルをネイティブに展開できるようになります。Player Settings で選んだ圧縮の方法に合わせます。gzip(`.gz`)は `Content-Encoding: gzip`、Brotli(`.br`)は `Content-Encoding: br` です。すでにファイルを圧縮するサーバー側の設定がある場合は、この設定に干渉して問題が出ることがあります。
Content-Type`.wasm`・`.wasm.gz`・`.wasm.br` は `Content-Type: application/wasm` で返します。WebAssembly のストリーミングコンパイルが働くには、サーバーが `application/wasm` の MIME タイプで返す必要があります。Decompression Fallback が有効だと、JavaScript の展開を通すので、WebAssembly のストリーミングは使えません。JavaScript を含むファイル(`.js`・`.js.gz`・`.js.br`)の Content-Type は `application/javascript` です。サーバーによって、これを自動で含めるものと、含めないものがあります。
複数スレッドの実験設定ネイティブの C/C++ のスレッドを使うには、Web の Player の設定で Native C/C++ Multithreading を有効にします。ドキュメントが安全なコンテキストの中にあるときに使え、サーバーが HTTP のレスポンスヘッダーを付ける必要があります。Cross-Origin-Opener-Policy には same-origin、Cross-Origin-Embedder-Policy には require-corp、Cross-Origin-Resource-Policy には cross-origin を入れます。複数スレッドの WebAssembly のビルドでだけ、ヒープメモリを初期化する `.mem` ファイルが作られます。
表4

サーバーごとの設定を示したコードサンプルのページには、Apache・IIS・Nginx・Node.js の項目があります。Unity のビルドのフォルダには、[名前].loader.js・[名前].framework.js・[名前].wasm・[名前].data などのファイルが入ります。

書き出したあとに確かめる手順

  1. 書き出し先のフォルダのファイルを見ます。Godot は、前の表の「ファイル・MIME タイプ・サーバー側の圧縮」の行のファイルが出ます。index.html は、親のディレクトリを開いたときにウェブサーバーがふつう既定で読むファイルで、そのファイル名はふつう見えなくなります。Unity は、Build フォルダに、[名前].loader.js・[名前].framework.js・[名前].wasm・[名前].data などが出ます。圧縮を有効にすると拡張子が付き、Decompression Fallback を有効にすると .unityweb になります。
  2. Godot では、Thread Support(Use Threads)を有効にして書き出したかを見ます。有効にしたときだけ、安全なコンテキストと、Cross-Origin-Opener-Policy に same-origin、Cross-Origin-Embedder-Policy に require-corp を入れたヘッダーが要ります。サーバーにヘッダーを足せない場合は、Progressive Web App > Enable の方法があります。
  3. Unity では、Compression Format と Decompression Fallback の組み合わせを見ます。Decompression Fallback が無効なら、.gz には Content-Encoding: gzip を、.br には Content-Encoding: br を付けます。.wasm 系のファイルには Content-Type: application/wasm を付けます。
  4. 書き出したファイルは、ファイルを直接開かずに、ウェブサーバーから開いて確かめます。Unity のプレイヤーをファイルシステムから直接開くと、ブラウザによっては動かないことがあります(ローカルのファイルの URL にセキュリティの制限があるため)。Godot では、Godot のリポジトリにある Python のスクリプト serve.py を、書き出したプロジェクトの index.html のあるフォルダに置き、そのフォルダのコマンドプロンプトで python serve.py --root . を実行すると、そのフォルダの中身が配られ、既定のブラウザが自動で開きます(プラットフォームによっては python を python3 に置き換えます)。Unity の Build and Run の内蔵サーバーは基本の機能だけで、データのキャッシュに対応しません。
  5. ブラウザの開発者ツールのコンソールを開きます。JavaScript・エンジン・WebGL のエラーなどが出ます。Godot では、ふつう F12 か Ctrl + Shift + I(macOS は Cmd + Option + I)で開きますが、Godot が入力を取り込んでいるためにショートカットが効かないことがあり、その場合はブラウザのメニューから開きます。
  6. 最初のクリックやキー入力のあとに、音が鳴るかを見ます。Unity のブラウザは、マウスのクリック・タッチ・キー入力があるまで音の再生を許しません。Godot でも、一部のブラウザが音の自動再生を制限しています。Chrome の自動再生のポリシーは、ある条件のもとで、音と動画の自動再生を防ぎます。たとえば、ゲームの読み込みの直後に BGM を自動再生する設定にしていても、ウェブサイトをクリックかタップするまでは自動では再生されません。
  7. 外部への通信を見ます。Unity で、ゲームを配るサーバーとは別のサーバーに UnityWebRequest で送ると、相手のサーバーが CORS で許可していない場合、ブラウザのコンソールに Cross-Origin Request Blocked で始まる文のようなエラーが出ます。サーバーが返事に Access-Control のヘッダーを足して、どのページに読む権限があるかを示します。たとえば Access-Control-Allow-Origin に * を入れると、どのオリジンからも読めます。Godot の HTTP のクラスは、同一オリジンポリシーの対象です。クリップボード・ゲームパッド・マイクは、HTTPS などの安全なコンテキストが要ります。

設定と、必要なものを図で見る

Godot の Thread Support のあり・なしと、Unity の Compression Format と Decompression Fallback の分かれ道を、設定と必要なものの対応だけで並べます。

設定と、サーバー側で要るもの

設定と、サーバー側で要るものWeb 向けの書き出しの設定設定ごとに、サーバー側で要るものが変わりますGodot:Thread Support(Use Threads)あり安全なコンテキストと、Cross-Origin-Opener-Policy に same-origin、Cross-Origin-Embedder-Policy に require-corp を入れたヘッダーが要ります(PWA の方法で、サービスワーカーがこのヘッダーがあるように見せかけられます)Godot:Thread Support なし1 スレッドの書き出しです。スレッドは使えませんUnity:Compression Format が gzip か Brotli(Decompression Fallback は無効)gzip の `.gz` のファイルには `Content-Encoding: gzip`、Brotli の `.br` のファイルには `Content-Encoding: br` を付けます。Chrome と Firefox は、Brotli に HTTPS でだけネイティブに対応していますUnity:Compression Format が Disabledビルドで圧縮しません。独自の圧縮をするか、ホスティングのサーバーで静的圧縮を使う場合の選択肢ですUnity:Decompression Fallback が有効`.unityweb` の拡張子が付き、JavaScript の展開の仕組みが埋め込まれ、ブラウザが展開に失敗したときに展開します
図1

失敗を避ける注意

Godot で Thread Support(Use Threads)を有効にして書き出したときは、必要なレスポンスのヘッダーをクライアントが受け取らず、サービスワーカーを使った方法も使っていないと、プロジェクトは動きません。安全なコンテキストも要ります。

Godot の Web のプロジェクトは、タブがアクティブでなくなると、ブラウザに一時停止されます。長いあいだタブを切り替えると、通信するゲームが切断されることがあります。フォーカスの外れたブラウザのウィンドウには、この制限は当てはまりません。

Unity の UnityWebRequest のダウンロードを待つために、while(!www.isDone) {} のようなブロックするコードは使えません。ブラウザは、同期的にブロックしてネットワークの転送を待つことを許さないためです。同期のように書きたいときは、Coroutine と yield で、ダウンロードの終わりを待ちます。

Unity の Build and Run で使われるサーバーは基本の機能だけで、データのキャッシュに対応しません。.data ファイルと、Addressables・AssetBundle のファイルに影響します。

このページの Unity の画面と設定の名前は Unity 6.0 のもの、Godot の名前は stable 版のものです。使っているエンジンの版によって、メニューや設定の名前が違うことがあります。

Godot で Web に書き出した結果を手元のサーバーで開いた記録は、Godotで書き出すと「export_presets.cfg」が無いと出るにあります。

次に読む

Web に書き出したファイルを ZIP にして公開先に上げる手順は、itch.io にゲームを出す手順にあります。

情報源

このページに出た言葉

このページの内容の誤りは、問い合わせの窓口で受け付けています。