前回で、単色の四角が絵に置き換わった。連載もこれが最終回だ。今回はゲームを Web 向けに書き出して、ブラウザで遊べるように公開しよう。

今回のゴール

  • 書き出しを頼むときの、制約の渡し方
  • AIが確かめられることと、人間が確かめることの分担
  • テストプレイで気づいたことを、遊び方に反映する判断

使ったもの

項目 値
Godot 4.7.2
コード生成AI Claude Code(Claude Opus 5.5)
検証日 2026-09-28

やり取り

同じプロンプトを投げても、同じ返答が返ってくるとは限らない。モデルが変われば中身も変わる。参考にしてほしいのは文面そのものより、どんな制約をどの順で与えたかのほうだ。

これまでと同じく、私の入力はコード枠で、AIの返答は引用で示す。やり取りの全文は、末尾の「制作の記録」にある。

書き出しを頼む

書き出したゲームは、DREAM THREAD のクラウドストレージ(Google Cloud Storage)に置き、このブログの記事から遊べるようにする。その前提と、置き場所の制約を並べて頼んだ。

このゲームを Web 向けに書き出して、ブラウザで遊べるようにしたい。

# 前提
- 書き出したものは、公開された Google Cloud Storage のバケットに置き、ブログ記事の中の枠(iframe)から遊べるようにする
- 置き場所は `https://storage.googleapis.com/godot-html/ai-game-dev-intro/` の下で、入口のファイルは `index.html` にしたい
- バケットへのアップロードは私が手でやる。あなたは書き出しとローカルでの確認までをお願いしたい
- Godot の書き出しは初めてで、必要なものがそろっているかも分からない

# 制約
- 置き場所のサーバーでは、特別な HTTP ヘッダーを付けられない
- 書き出したファイルは、リポジトリには入れない(`build/` に出力する。`.gitignore` 済み)
- スマホの縦持ちでも遊べること

# 進め方
いきなり書き出さず、先に次を見せてほしい。私が確認して OK を出してから作業すること。

- 書き出しの前に私がやる必要のある準備(ダウンロードなど)
- 書き出しの設定で変える項目と、その理由
- 書き出したものを、ローカルでどう確かめるか

書き出し終えたら、ブラウザで起動できるかを自分で確かめてから報告してほしい。報告は日本語で書くこと。

このプロンプトには「スレッドを無効にして」とは書かず、「特別なヘッダーを付けられない」という制約だけを渡した。

AIの下調べ

AIは、まず手元の Godot と、書き出しに要る「テンプレート」がそろっているかを調べてきた。

  • 書き出しテンプレート: 4.6.stable しか入っていません。本体とバージョンが違うと書き出せないので、4.7.2 用がないと進められません

書き出しの設定の表には、スレッドサポートを「オフ」にする行があり、その理由に「オンにすると、サーバー側で COOP/COEP という特別なヘッダーが必要になります。GCS では付けられないので、ここがいちばん大事な設定です。」と書いてあった。AIは「特別なヘッダーを付けられない」という制約から、スレッドを無効にする設定を自分で選んでいた。確かめ方も、置き場所に合わせてあった。Godot エディタの「ブラウザで実行」は特別なヘッダーを付けて配信するので使わず、ヘッダーを付けない普通のサーバーで配信し、ブログと同じように別の場所の枠(iframe)から開く、という。

書き出しの設定の全体と、アップロードの注意
項目 設定 理由
書き出し先 build/web/index.html 入口を index.html にしたいとのご希望どおり。.gitignore に /build/ がなければ追加します(今の .gitignore には書かれていません)
スレッドサポート (variant/thread_support) オフ オンにすると、サーバー側で COOP/COEP という特別なヘッダーが必要になります。GCS では付けられないので、ここがいちばん大事な設定です。オフにしておけば、iframe の中でもそのまま動きます
PWA オフ Service Worker が古いファイルを覚えてしまい、更新が反映されない原因になりやすいため
テクスチャ圧縮 既定のまま 画像はすべて無圧縮なので影響しません
デバッグ版 / リリース版 リリース版 容量が小さく、動きも軽いため
描画方式 変えない プロジェクトは Mobile ですが、Web では自動で Compatibility(WebGL2)に切り替わります。見た目が変わらないかは確認のときに見ます
  • .wasm のファイルは Content-Type が application/wasm になっているか確かめてください。gcloud storage cp やコンソールからなら、普通は自動でそうなります
  • .wasm は約 35MB あります。gcloud storage cp --gzip-in-flight-all ではなく、-Z(gzip で圧縮して保存) を使うと転送量を大きく減らせます。これはファイルに付ける情報で、特別なヘッダーには当たりません
  • GCS の公開ファイルは、既定で 1 時間キャッシュされます。更新してもすぐに反映されないことがあります

判断した1:準備もAIに任せる

AIは、テンプレートは私が Godot エディタからダウンロードしてインストールするように、と書いていた。私はこう返した。

テンプレートのインストールはそちらで実施して

AIは Godot の公式の配布元からテンプレートをダウンロードし、公式に公開されている値と照らし合わせて、ファイルが正しいことを確かめてからインストールした。

  • 入手元: Godot の公式 GitHub Releases から Godot_v4.7.2-stable_export_templates.tpz(約 1.2GB)をダウンロードしました。SHA512 チェックサムは公式の値と一致しています。

「OK」と返すと、AIは書き出しの設定ファイルを作ろうとした。ところが、Claude Code の安全確認の仕組み(Auto モードの判定)がエラーを繰り返し、5回続いたところでAIは作業を止めた。

このエラーは操作が危険と判断されたものではありません。判定するサーバー側の一時的な不具合です。止めた時点で、ファイルは何も作っておらず、何も変更していません。

少し間をおいて、こう送った。

エディターが開いていたので閉じました。
もう一度試して

今度は通り、AIは書き出しを終えて、自分で確かめた結果を報告してきた。

  • 起動: Godot 4.7.2 が WebGL2(Compatibility)で起動しました。crossOriginIsolated が false、つまり特別なヘッダーがなくても動いています
  • タップで遊べるか: 「TAP TO START」のタイトルが出ました。タップでステージ 1 が始まり、そのまま操作していないのでゲームオーバーまで進みました(ログに stage 1 start と game over が出ています)
  • エラー: コンソールのエラーも、読み込みに失敗したファイルもありませんでした
  • 見た目: スクリーンショットで確かめました。スマホ幅でも 9:16 の枠にぴったり収まり、背景・壁・忍者・文字も正しく表示されています

AIは、スマホの画面の大きさを再現したブラウザで起動し、画面を撮って確かめていた。そのうえで、確かめられなかったことも書いてあった。

音は、自動の確認では耳で確かめられていません。 特にチャージ音の高さの変化は、ご自身で聞いてみてください。

  • アップロードした後、実機のスマホ(HTTPS)で一度遊んでみてください。本物の端末で確かめるのは、この段階が初めてになります

書き出したファイル一式は、HTTPS で配信できる場所に置けばブラウザで遊べる。この連載では、DREAM THREAD のクラウドストレージに私が手で置いた。置き場所の選び方とその手順は、この連載の範囲を超えるので、別の機会に扱う。

判断した2:テストプレイで遊び方を直す

絵と音がついてから何度もテストプレイしているうちに、遊び方そのものにも気になるところが出てきた。本来は第3回で決めておくべき内容だが、このタイミングで直すことにした。

ステージクリアは、渡り廊下にプレイヤー自身がタッチした時に成立する。
スタミナを使い果たした場合はジャンプできず、そのまま落下死する
BGのうち、町並みとそれ以外の2層構造に分ける。町並みは一つ手前のレイヤーに置かれ、プレイヤーの上昇とともに画面下部にはけていく。

AIは3つとも直し、背景の町並みは、元の背景の絵から切り抜いて別の絵にしていた。報告の最後には、自分で決めたことが並んでいた。

  • 町並みの戻り方: ゲーム全体で登った距離で動かしています。ステージ 2 以降では町並みは出てこず、リトライしたときだけ元の位置に戻ります。ステージごとに毎回町並みから始めたい場合は、1 行の変更で切り替えられます。
  • はける速さ: 0.4 倍にしました。今の速さだと、登り始めて数秒で消えます。エディターの Main ノードにある town_parallax で調整できます。
  • 落下中の当たり判定: 落下中もコインは取れますし、トゲにも当たります。

私が指示していないところは、AIが決めてから知らせてきた形だ。2つ直してもらった。

ステージは毎回町並みから始めたい。
はける速さを0.2倍にして

直った版を確かめて「OK」と返した。

書き出し先を読み込ませない

最後に1つ頼んだ。

build/ フォルダを Godot が読み込まないように、build/.gdignore を置いてほしい。すでにできている build/web/*.import も消して、書き出しをやり直してほしい

書き出し先の build/ はプロジェクトの中にあるので、Godot が書き出したアイコン画像を素材として読み込み始めていた。AIは空の .gdignore を置き、読み込んだ跡を消してから書き出し直した。

  • .pck は約 24KB 小さくなりました。前回までは、書き出したアイコン画像がゲームのデータに一緒に入っていたようです。

別のセッションで出たエラー

作業を終えたあと、スクリプトを開いていた VS Code にエラーが出ていたので、別のセッションで聞いた。

エラーが出ている

AIは Godot でスクリプトを確かめ、エラーは再現しないと言って、エラーの文面を貼るよう求めてきた。

189行目
Could not find type "FallingObject" in the current scope.

コードに問題はありません。原因は、Godot がクラス名を覚えておくための一覧(キャッシュ)が古くなっていたことだと思われます。

このエラーは第5回の作業中にも VS Code に出ていて、そのときもAIは、ゲーム本体の問題ではないと説明していた。今回は、クラス名の一覧のファイルがいつ更新されたかまで調べて原因を絞り込み、Godot エディタでプロジェクトを再読み込みすれば直る、と示してきた。

動かしてみる

起動直後の画面。満月の夜空の下、画面の下に町並みの屋根が見え、左の石垣に忍者が張り付いている。中央に TAP TO START と出ている

起動すると、画面の下に町並みが見える。登るにつれて町並みは下へ抜けていき、頂上の渡り廊下に触れるとステージクリアだ。下の「▶ 遊ぶ」から、このページで遊べる。

今回のハマりどころ

書き出しには、Godot 本体と同じ版のテンプレートが要る。 私の手元には古い版しか入っていなかった。しかも、テンプレートを探す場所は Godot の入れ方によって違う。AIも最初は違う場所に入れてしまい、書き出しの途中で移し直していた。

書き出し先をプロジェクトの中に置くと、Godot がそれを素材として読み込む。 書き出したアイコン画像が、次の書き出しに紛れ込みかけた。そのフォルダに空の .gdignore を置いておけば、Godot はそこを無視する。

プロンプトの前提に書いたことが、事実と違う場合もある。 私はプロンプトに「.gitignore 済み」と書いたが、実際には build/ の設定は入っていなかった。AIは下調べでそれに気づき、書き足してから報告してきた。

スマホの実機と音は、AIには確かめられない。 AIはスマホの画面の大きさを再現したブラウザで起動を確かめたが、本物の端末でのタッチや音の聞こえ方は確かめられないと自分で書いていた。公開したあとに、実機で一度遊んで確かめる必要がある。

今回のコード/遊ぶ

ai-game-dev-publish(GitHub のタグ)。これが完成版で、第4回・第5回のタグも同じ状態を指している。この回で増えたのは、Web 向けの書き出しの設定 export_presets.cfg だ。ブラウザで遊ぶなら、下の「▶ 遊ぶ」から。

この回のやり取りの全文は、制作の記録(第6回)にある。

次回やること

連載はこれで完結する。番外編では、AIに作業させるときに欠かせないバージョン管理を扱う予定だ。