Contents — 8 sections
対人戦用のアリーナを、毎回手で作るのをやめたかった。
そこでRicochetTanksでは、点対称のMapをseedから生成するMapGenを作った。
同じseedなら同じ配置。
サイズごとに300候補を一括生成。
最初は、
「300個作れば、その中から良いのを選べる」
くらいに考えていた。
実際に回すと、合格率はかなり低かった。
初版は16〜37%しか通らなかった
第1版を3サイズ、それぞれ300候補で生成した。
結果は、
| Arena | Pass | Pass rate |
|---|---|---|
| 24 × 20 | 111 / 300 | 37.0% |
| 32 × 26 | 65 / 300 | 21.7% |
| 40 × 32 | 48 / 300 | 16.0% |
大きいMapほど、初版の条件では落ちる割合が増えた。
生成自体はできる。
でも「ゲームとして候補に残す」まで行くMapは少ない。
ここで、MapGenの仕事は配置をランダムに作ることではないと分かった。
ダメなMapを自動で捨てることの方が重要だった。
何をrejectするか
RicochetTanksは、壁で一度跳ね返した弾を当てるゲーム。
だから単に、
- 通路がつながっている
- Playerが歩ける
- 壁が重なっていない
だけでは足りない。
見たいのは、
- 開幕から一方的に危険でないか
- 一回反射の射線が成立するか
- 同じ壁だけが使われ続けないか
- 中盤で複数の反射面が使えるか
- 行き止まりや不自然な詰まりがないか
のような、Gameplay側の条件。
Map Generatorではなく、Map Filterが必要だった。
第1版の検査自体を作り直した
初版を回した後、検査ロジックを作り直した。
これは重要だった。
「合格率が低いからGeneratorを強くする」
ではなく、
そもそも合格判定が欲しいゲーム性を測れているか
を見直した。
第2版では、同じく各300候補を回した。
結果は、
- 32 × 26: 114 pass、うち106 unique
- 40 × 32: 171 pass、171すべてunique
まで改善した。
MapGen検査自体も24 PASS / 2 NOT_RUNまで残した。
生成時間も普通にかかる
第2版では、
- 32 × 26: 799秒
- 40 × 32: 1,128秒
かかった。
全体の実経過は約81分。
そのうちUnity側の生成待ちが約32分。
これは人時ではない。
AgentやProcessが待っている時間も含む実経過。
生成を自動化しても、計算・Unity処理・検査には時間がかかる。
良さをProxy Metricへ落とした
第2版では、合格候補についてさらに数字を取った。
「最初の脅威までの時間」は、
- 32 × 26: 1.5〜4.9秒、中央値2.6秒
- 40 × 32: 1.5〜5.7秒、中央値2.2秒
中盤で使われる反射面数は、
- 32 × 26: 5〜16、中央値8
- 40 × 32: 6〜23、中央値12
だった。
もちろん、この数字だけで「面白いMap」とは言えない。
ただ、
見た目で300枚眺めるより、候補を絞るProxyとしては使える。
上位seedも「採用」ではない
40 × 32ではseed 53が上位候補になった。
評価上は、
- 開幕の被弾方向 0
- 中盤の組の64%で一回反射可
- 反射面14種類
という値。
上位3件は確認用Sceneへ出した。
でも、この時点ではまだ「最終Map決定」ではない。
Rankingは人間レビューの前処理。
ここも自動生成と自動決定を分けた。
Procedural Generationは「量産」より「選別」
Procedural Generationというと、
「無限にMapを作れる」
が目立つ。
でも実際の開発で欲しかったのは、無限のMapではなかった。
使えないMapを人間が見なくて済むこと。
300個作って、300個レビューするならあまり嬉しくない。
300個作って、検査で100個以下に減らして、その中から上位だけを見る。
そこまでやって初めてAutomationの意味が出る。
いまの結論
MapGenで一番重要だったのは、乱数でも配置アルゴリズムでもなかった。
何を失格にするか。
生成器が賢くなるほど、もっともらしい失敗作も大量に出せる。
だから生成と同じくらい、reject ruleを育てる。
RicochetTanksのMapGenは、Mapを作る実験というより、ゲーム性を機械判定へ落とせるかの実験になった。