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を作る実験というより、ゲーム性を機械判定へ落とせるかの実験になった。