はじめに
この記事では、知見のない分野の開発で、AIと二人三脚で進められる体制をどう組み立てたかについてまとめています。
AIに複雑なものを作らせると、一見それらしいものが一発でできることも珍しくありません。
しかし、そこへ要素を追加し、満足できる形までブラッシュアップし、さらに拡張性を持たせようとすると、ブラックボックスのままAIに任せ続けるだけでは、いずれ 「AIに丸投げしても解決できない詰みの状態」 に陥ります。
もちろん、事前に設計を徹底的に詰めておけば、こうした問題をある程度は避けられます。
ただし、Webシステムのように既存の類型や定石を参照しやすい分野と違い、ゲーム開発では、同じジャンルでも仕様や遊びによって適切な実装方法が変わりやすく、事前に正解の設計を固めにくい場合があります。
そこで今回は、実際に生成を動かして問題を炙り出しながら、生成ロジックそのものの整理、AIに共有すべき情報の整理、ログやデバッグ情報を収集する仕組みの構築を進めました。
本記事では、そうして複雑化したプロシージャル生成を観測可能にし、AIと一緒に修正・改善できる状態へ持っていくまでを扱います。
なぜ「観測できる仕組み」が必要になったか
最初は、プロシージャル地形の生成ノウハウも、道・川・橋を一体で扱う設計も、ほぼありませんでした。
Cursorには大まかな要件だけを伝え、
- 3Dで、シードから地形・道・川・橋まで出したい
- 自然地形に沿って道が走り、渡河には橋が載るイメージ
といった要求から実装を進めました。
すぐに問題が出始めます。道が乱れる、橋と道の接続が合わない、地形だけ荒ぶる——症状は似ていて、原因工程はバラバラです。
コードだけAIに読ませても、「どのシードの、どの地点の、どの工程の」話かが伝わらず、修正が当たり外れになりました。
つまり、AIの実装能力そのものよりも、「今何が起きているのか」を人間とAIが共有できないことがボトルネックになりました。
そこで人間側が要素を整理しながら、
- 生成の大まかなロジックの順番(地形 → 道の経路 → 凹凸 → メッシュ)を整理する
- 対策(デバッグ表示、ピン、ステップ再生、診断ログ)を足して、壊れ方まで追えるようにする
- それらをAIが推測に頼らず参照できる観測記録(ログ・座標・工程名)として残す
という環境を整えました。以降は人間が目視とログで状況を把握し、Cursorには再現可能な事実を渡し、コードを修正する、という二人三脚で回しています。
本文後半に、その対策の要件と中身、Cursorへの渡し方をまとめています。
前半の「マップ生成の概要」は、何を作っているかの説明です。アルゴリズムの詳細や数式は別記事のスコープとします。
この記事でCursorがやっていること
- やる: 診断ログ・ピン記録・リポジトリ内のソースを読み、症状に対応する工程を絞って修正案を出す
- やっていない: スクリーンショットのVision解析だけで原因を特定する
目視は人間がデバッグ表示やPlay中の画面で行い、AIにはテキストの観測結果(ログ、シード、ピン座標、工程名)を渡します。
技術構成(概要)
| 項目 | 内容 |
|---|---|
| エンジン | Unreal Engine 5.8 |
| 実装 | C++ が中心(ゲーム側のアクターに生成ロジック) |
| 地形表現 | Landscape / PCG Frameworkは使わず、独自の高さ配列(高さ場)とProcedural Mesh Componentで地形・道・川・橋をメッシュ化 |
| 道・川の経路 | 2Dポリライン+レイアウトグラフ(後述)。UE標準Splineは使っていない |
| 生成タイミング |
ランタイム(Play開始時などにGenerateTerrain)。エディタ専用ベイクではない |
| 乱数 |
WorldSeedとFRandomStreamで生成。開発中は同じPC・同じビルド・同じシードで不具合を再現することを目的としており、クロスプラットフォームのbit完全一致までは狙っていない |
マップ生成の概要
ここからは、上記の生成器が何を出力するかの説明です。
プロシージャル生成とは(この記事での意味)
完成した地図アセットを置くのではなく、ルールとシード値から地形・道・川などを組み立てる方式です。
単なる「ランダム配置」とは違い、同じ開発環境・同じシードなら同じ地図を再現できることが、後述のデバッグの前提になります。
やりたいこと
手置きのオープンワールドではなく、同じシードなら同じ地図が出る3Dフィールドです。
| 要素 | 内容 |
|---|---|
| 地形 | 土地の傾斜・凹凸に加え、川とそれに伴う浸食もひとまとめに扱う「地形」 |
| 道 | 自然地形に沿って引かれる道路網。最低限の整備で通す |
| 橋 | 道と川が交差したところの設置物。道は橋のソケットに結合する |
| その他 | 道の自然な凹凸、プロシージャルメッシュ、木・岩・草など |
建付けとしては、先に地形を決め、その上に道と橋を敷くイメージです。道や橋が地形を無視して走るのではなく、傾斜や河床に合わせて経路が決まり、整地は必要最小限に留めます。
工程の順番(大別5段階)
内部的には細かく約64工程に分かれていますが、大別すると次の5段階で捉えています。
- 地形 — ランドフォーム、大きな傾き、高さ場(格子状の高さデータ)。川の流路と河床まわりの浸食もここで扱う
- 道の経路 — 地形に沿った道路の経路(合流・渡河・橋との接続位置まで)
- 道の自然な凹凸 — 勾配、デッキ高さ、道床のcut/fill(地形を削る/盛る)、水路の再奪還など
- メッシュ — 地形/道/川/橋の見た目
- 小物 — 木・岩などの配置
「道を先に全部決めてから川だけ後から掘る」「メッシュを先に出してから高さを直す」ような順ではありません。
地形 → 道の経路 → 道に沿った凹凸の流れです。川も地形の一部として最初から関与し、道はその結果に追随します。
ノード管理(レイアウトグラフ)
道・川・橋・合流・交差を、線(ポリライン)と設置物として管理する仕組みを導入しています。
FigmaのコネクタやUEのBlueprintのように、各設置物が持つソケット(ポート)に、道の端が結合していることを接続関係の基準データとして扱います。
Road0 ──→ [ In | Bridge | Out ] ──→ Road1
│
River(川パス)
橋についても「見た目でなんとなく道を寄せる」のではなく、
- 橋デッキにIn / Outのソケットがある
- 道は物理的に切断され、先端がそのソケット位置・向きに載る
- 橋を動かす・回すと、接続された道がソケットに追従する
という接続関係を担保しています。合流や道同士の交差も、同じくポートとリンクで表現します。
この方式にしておくと、
- 新しい建築物 — 道に接続する設置物を、ソケット+リンクの仕組みで追加しやすい
- 手動マップ編集(将来) — 生メッシュの大量配置ではなく、同じグラフをGUIから読み書きする想定
- 差し替えコスト — 橋モデルを変えても、ソケット位置が合えば接続された道は追従する
生成ログやデバッグ表示(後述)も、このグラフを可視化しています。不具合調査では「座標がずれた」だけでなく「どのリンクが切れたか/どのソケットで接続がずれたか」を追います。
よくある不具合
プロシージャルで道・川・橋を同時に扱うと、症状は似ていても原因工程が違うことが多いです。
道が乱れる
- 川を何度もジグザグに渡る
- 並走が二重線のまま残る、または逆に一本に潰れて分岐が消える
- ヘアピン・針状の突起、自己交差
- 橋の手前だけ不自然に曲がる/岸に吸い寄せられる
橋の配置がおかしい
- 川と平行に近い道なのにデッキが載る(かすり交差)
- デッキが河床の真ん中に来ない、岸に寄る
- 道の先端がソケットに届かない、またはデッキを貫通する弦が残る
- 高さが水面より低い、アプローチだけ宙に浮く
地形が荒ぶる
- 道の帯だけ崖・溝になる(cutしすぎ/fillしすぎ)
- 川を盛土で埋め戻したあとに水路が戻らない
- 道と川に挟まれた細い帯がギザギザになる
- 仕上げパスが「直したつもり」で別の場所を削る
見た目だけ見ると全部「地形が壊れた」に見えます。実際は道の経路(平面)の失敗と道に沿った凹凸・高さの失敗が混ざります。ここを切り分けるために、次の対策を足しました。
対策1: デバッグ表示モード(レイアウトの可視化)
完成メッシュだけ見ていると、道や橋の不具合が「地形が変」に見えて原因が掴みにくいです。
レイアウトグラフの中身をワールド上に重ねて見るデバッグ表示モードを用意しています。
F3で切り替えます。ONにすると次が表示されます。
| 表示 | 内容 |
|---|---|
| 道のパス | 内部で管理している道路ポリライン(橙系の線) |
| 川のパス | 川ポリライン(青系) |
| 名前・ラベル | 各道路フラグメントや文字列ラベル(合流区間名など) |
| 設置物 | 橋・合流・交差の位置(黄=橋、緑=合流、マゼンタ=交差が目安) |
| ソケット | 各設置物のIn / Outなどポート位置と向き(矢印付き) |
| HUDパネル | カメラ位置、レイアウト件数、ステップ再生状態、ピン数など |
メッシュの見た目ではなく、内部で管理している配置と名前を確認できます。
人間が画面上で確認し、必要ならCursorには「ピンAのBridge#2のOutソケット付近で道が届いていない」など、目視した結果を言葉にして渡します。
ステップ再生やデバッグ飛行と組み合わせると、工程を1段進めるたびにパスがどう変わったかを追えます。
デバッグ表示:橙=道、青=川、黄=橋、緑=合流、マゼンタ=交差。ラベルとソケット矢印が内部状態を示す

対策2: ピン立て(調査ランドマーク)
「このシードの、あの曲がり角」を口で説明するのは難しいです。ワールド座標をメモしても、再生成のたびに視点を合わせ直すのが面倒です。
そこで調査ピンを足しました。
| 操作 | 内容 |
|---|---|
Alt + 0〜9 / A〜Z
|
今いる位置にピンを立てる(上書き) |
Alt + Ctrl + 同じキー |
そのピンへワープ(少し浮かせる) |
Alt + Shift + 同じキー |
そのピンを消す |
Alt + Delete
|
今のシードのピンを全部消す |
| コンソール | ピンを置く/ワープするコマンドもある |
ピンはシード+マップ名ごとにログ用フォルダへ残ります。同じシードで再生成しても配置情報は引き継がれ、HUDにも一覧が出ます。
Cursorには「ピン1の橋がおかしい」と伝えるだけで、都度座標を指定せずに調査地点を共有できます。そこから診断ログの橋まわりの行と突き合わせて、該当の箇所を絞り込みます。
対策3: ステップ再生
一発生成だと、最終メッシュだけ見て「どこで壊れたか」が分かりません。内部は約64工程あるため、ログだけでも追い切れないことがあります。
ステップ再生は、生成を工程単位で止めて中を見られるようにしたものです。
| 操作 | 内容 |
|---|---|
| コンソールでステップ再生を開始 | 任意の工程番号まで一気に進めてから止めることもできる |
F7 |
次の工程へ進む |
F6 |
一つ前まで戻す(一つ前の工程まで生成し直す。undoではない) |
| デバッグ飛行 | 地形透過のデバッグ飛行。ステップ確認中は自動でONになることもある |
| デバッグ表示 | 対策1のレイアウト重ね描き |
F6で戻すと、一つ前の工程まで最初から再生成するため、1段戻るたびに時間はかかります。プロシージャルは途中状態の差分パッチが難しく、正しさ優先でこの方式にしています。
「橋を置く直前まで飛ばして、F7で次の工程だけ見る」といった使い方ができます。道が乱れる系は経路決定側、地形が荒ぶる系は勾配・cut/fill側、と当たりを付けやすくなります。
対策4: ステップごとの生成ログ
生成のたびに、最新の1回分だけを常に上書きする診断ログを出力します。同じ内容のタイムスタンプ付きコピーも残り、ヘッダにシードと再現用コマンドが入ります。
診断ログは、AIが「たぶんこうでは」と推測するのではなく、その実行で実際に起きたことを判断するときの基準になる記録です。
載っているものの例:
- STEPタイムライン — 各工程の開始/終了。行頭に経過msがあり、工程ごとの処理時間が読める
- 要所の理由 — なぜ迂回したか、なぜ渡河を岸沿いに書き換えたか、なぜ橋をスキップしたか
- 高さのcut / fill — どの基準で、どこを削った/盛ったか(座標、高さ差、道や川からの距離)
- レイアウトスナップショット — 川・道の本数とサンプル点、高さ場のmin/maxなど
- 再現 — ログに書かれたシードで再生成する手順
工程時間からボトルネックを洗う
ログは不具合調査だけでなく、生成全体がどこで時間を食っているかを見る用途にも使います。
作業の区切りごとにmsを眺め、異常に伸びている工程を優先してロジックの見直しに入ります。
ある時期、あるシードでは、生成全体に約60秒かかる状態がありました。
ログのSTEPタイムラインから処理時間の大部分を占めている工程を特定し、そのアルゴリズムを見直した結果、生成全体を約1秒程度まで短縮できました。見た目の結果は意図どおり維持できています。
このように、工程ごとの処理時間を記録しておくことで、生成全体のボトルネックを工程単位で切り分けられます。
各機能とAI(Cursor)の使い方
調査機能は人間用のほか、Cursorがコード修正の前に読む材料として設計しています。役割の分担は次のとおりです。
- レイアウトグラフ — 道と設置物の接続関係の基準データ
- 診断ログ — その実行で実際に起きたことの記録(工程・理由・msなど)
- Cursor — 主にログとピン記録を読み、該当工程のソースを絞って修正案を出す
リポジトリには地形デバッグ用のCursorルール(mdc)があり、だいたい次の順で頼みます。
- 最新の診断ログを読む(工程タイムラインとms、橋・高さ編集の行)
- 人間がデバッグ表示で該当地点を目視し、必要なら症状を短文で補足する
- 実装の索引から、症状に対応するソースを選ぶ
- 該当箇所だけ読む(巨大な生成器ソースを頭から読まない)
- 工程の実行順は、頼まれない限り並べ替えない
- 修正後、ログヘッダのシードで再生成して確認する
人間: 不具合を見る → デバッグ表示/ピンで地点を固定
→ 必要ならステップ再生
→ Cursorに「シード・工程・ピン・症状・ログの該当行」を渡す
AI: ログとピン記録を先に読む → 工程を絞る → 修正案
人間: 同一シードで再生成 → ログと画面で確認
プロシージャルは「コードを読んだだけでは再現できない」。シード・地点・工程ログ・レイアウト可視化を揃えて初めて、AIとの往復が調査になります。
まとめ
- 主旨: 知見のない状態からCursorと開発を始め、複雑化した生成器を観測可能にして、二人三脚で直せる環境を整えた話
- 生成: 地形(傾斜・凹凸・川と浸食)→ 道の経路 → 凹凸 → メッシュ → 小物。内部は約64工程だが、大別すると5段階
- レイアウトグラフ: 設置物のソケットに道が結合する接続関係の基準データ
- 対策: デバッグ表示、ピン、ステップ再生、診断ログ(工程ms含む=実行結果の記録)。人間が目視、AIにはログと再現条件を渡す
- 性能例: ログでボトルネックを洗い出し、生成全体が約60秒 → 約1秒になった事例あり
叩き時点では、個別バグの詳細事例は後で足す想定です。

