AIゲーム制作ラボ
Unity×AI8分で読めます

Unityの自動生成ステージを理不尽にしない設計(1000種の自動検査つき)

AI に地形を自動生成させると、避けようのない配置がときどき混ざります。あとから弾くのではなく「作られない」構造にして、1000種類の種で毎回検査した記録です。その検査で見つかった設計ミス5件も、そのまま載せます。

Libra

公開 2026年9月18日

この記事の要点4 points

  1. 理不尽な地形は検査で見つけるのではなく、作られない構造にする 先に正解の道を引き、その道が通らないすき間だけを塞ぐ。
  2. 1000種類の種で「想定どおりに遊べば助かるか」を毎回自動で確かめる。 この1件のテストは5.93秒で終わる。
  3. 設計ミスは5件見つかったが、そのうち4件人が遊んでいてもまず気づけない種類のものだった。
  4. AI は地形の見た目をいくらでも増やせる。 遊べるかどうかを保証できるのはテストだけだった。
目次7
検証した環境最終確認 2026年9月18日
  • Windows 11
  • Unity 6.6(6000.6.0f1)
  • Claude Code(Opus 5 / 思考レベル 高)

書いてあるのは、この環境で実際に試した結果です。ツールの仕様や料金は変わるので、重要な判断の前には公式の情報も確認してください。

壁から壁へ跳び移って登るゲームを AI に作らせました。地形は毎回作り直されます。作り始めてすぐ、いちばん厄介な問題が出ました。ときどき、どう跳んでも死ぬ地形ができる。

しかも、遊んでいる本人には「自分が下手だったのか、地形が無理だったのか」が分かりません。

1000種

毎回検査する種の数

高さ120mまで

5.93秒

その検査1件の実行時間

エンジンを起動しない

5件

検査で見つかった設計ミス

人の目では見つからない

81秒

完璧に遊んだときの1プレイ

20種の中央値・391m

「作ってから確かめる」は間に合わない

最初に思いつくのは、地形を作ってから「クリアできるか」を判定して、だめなら作り直すやり方です。これは2つの理由でうまくいきませんでした。

ひとつは、判定そのものが難しいこと。「跳べば届く」は、そのとき選んだ跳び方によって変わります。もうひとつは、作り直しが無限に続く可能性を消せないこと。

理不尽な地形を弾くのではなく、理不尽な地形が作られない手順にする。

先に正解の道を引いてから、残りを塞ぐ

やり方は単純です。地形を作るとき、最初に「こう遊べば登れる」という道を決めてしまう。壁に張り付いて登る区間、跳ぶ高さ、着地する高さを、生成する側が先に決めます。

  1. STEP 01

    正解の道を引く

    登る区間・跳ぶ高さ・着く高さ

  2. STEP 02

    安全地帯を確定

    その道が通った所

  3. STEP 03

    残りのすき間を塞ぐ

    トゲ・天井はここにだけ

この順番で作るかぎり、正解の道は必ず残る

トゲを置けるのは「正解の道が通らなかったすき間」だけです。難易度を上げたいときは、すき間を埋める割合を上げます(このゲームでは高さに応じて 0.45 → 1.0)。埋め方をどれだけ厳しくしても、道そのものは消えません。

同じ考え方は、あとから足した要素にも効きました。空中に張り出す天井を足したときも、壁の幅を高さで変えたときも、「正解の道を先に決めてから、その道と当たらないことを確かめて置く」という手順は変えていません。

1000種類の種で、毎回確かめる

設計が正しいかどうかは、人の目では確かめられません。地形は種(シード)から作るので、種を変えて総当たりで遊ばせるテストを書きました。

[Test]
public void 千種類の種で正解の道をなぞれば高さ120mまでは必ず生き残れる()
{
    var failures = new List<string>();
    for (int seed = 1; seed <= 1000; seed++)
    {
        if (!LevelGenerator.CanSurviveIntendedPath(Tuning.Default, seed, 120f, out var failure))
        {
            failures.Add(failure);
            if (failures.Count >= 5) break;
        }
    }
    Assert.That(failures, Is.Empty, "回避できない地形が作られた: " + string.Join(" / ", failures));
}

CanSurviveIntendedPath は、生成器が引いた正解の道をそのまま再生するだけの関数です。1/120秒 刻みで当たり判定を進め、死んだら失敗として返します。

エンジンに依存しない形で書いておく

このテストが数秒で終わるのは、遊びのルールが MonoBehaviour から切り離してあるからです。プレイヤーの移動・地形の生成・当たり判定は、UnityEngineVector2Mathf しか使わない普通のクラスに置いてあります。描画とエンジンを通さないので、Play モードに入る必要がありません。

Git BashOK
$ unity command run_tests --mode EditMode --filter "千種類"
run_tests	true	1/1 件成功 (EditMode, 5.93s)

検査で見つかった設計ミス5件

ここからが本題です。このテストは、書いたその日から落ち続けました。 落ちるたびに出てくるのは、こちらの設計の穴でした。

01

想定した遊び方が、追ってくる危険より遅い

バランス調整 20分
症状
種に関係なく、全部の種が高さ54m付近で死ぬ
原因
生成器が想定する遊び方(壁で少し待ってから跳ぶ)の登り速度が毎秒 1.98〜2.57 で、下から追ってくる線の速度 2.0〜3.1 より遅かった。地形は正しいのに、正解の道を通っても追いつかれる
対処
跳ぶ速さを上げ(横 12→14・上 9.8→10.5・重力 18→19)、追ってくる線を 1.5〜2.8 に下げた
02

1つの種だけが108mで死ぬ

原因の特定 25分
症状
1000種のうち seed 659 だけが高さ108mで死ぬ
原因
生成器が「壁で待てる時間」を、下から迫る速さを見ずに決めていた。高い所では待つ余裕が無いのに、長めの区間を作ってしまう種があった
対処
壁で待てる最大時間を、その高さの帯の速さから逆算して上限にした(余裕は20%)
03

天井の高さを「弧の真ん中」で計算していた

やり直し1回
症状
空中の障害物を足したとたん、多くの種が116〜120mで死ぬ
原因
跳んだ弧は着地する瞬間まで上がり続ける形だったので、「真ん中の高さ」は通れる保証にならなかった
対処
障害物の端を通る時刻での高さを基準にした
04

天井が、次の跳びの昇り始めと重なる

やり直し2回目
症状
③を直しても、まだ同じあたりで死ぬ種が残る
原因
置いた天井が、いま跳んでいる弧ではなく次の跳びの昇ってくる途中と重なっていた
対処
天井はいったん保留し、次の跳びの高さが決まってから「当たらない」ことを確かめて置く形にした
05

1フレームだけの入力が、毎回わずかに強い跳びになる

ズレの原因探し 15分
症状
正解の道と実際の位置が、40回跳ぶと 2.4m ずれる
原因
押した長さで跳び方が変わる操作(溜め跳び)を足したとき、タップでも1フレーム分は押したことになり、そのぶん毎回強く跳んでいた
対処
溜めに 0.07秒 の遊びを入れた。タップは毎回まったく同じ跳びになる

5件のうち4件は、人が何十回か遊んでやっと1回踏むかどうかの頻度でした。

人力のテストプレイでは、まず見つかりません。見つかったとしても「いまのは自分のミスだったかも」で流れてしまいます。

「必ず終わる」も、同じやり方で決めた

作っている途中で、別の問題も出ました。上手く遊ぶと永遠に続いてしまう。 スコアを競う形にするなら、いつかは必ず終わってほしい。

そこで、下から追ってくる帯の速さを「1m 登るごとにいくつ上げるか」で調整しました。数字を4通り試して、機械が完璧に遊んだときの1プレイの長さを測っています。

1m ごとの加速と、1プレイの長さ(機械が完璧に遊んだ場合)
  • +0.01479秒
  • +0.01858秒
  • +0.02246秒
  • +0.02836秒

人は機械より下手なので、機械で長めに出る設定を選んだ。いまの版では中央値 81秒(74〜88秒)・391m

この「必ず終わる」も、テストにしてあります。20種類の種で完璧に遊ばせ、600秒たっても終わらなければ失敗、1プレイの長さの中央値が 45〜115秒 から外れても失敗にしました。数字を触ったときに気づけるようにするためです。

AI に地形の生成を書かせるときに渡したもの

やってみて分かったのは、AI に「面白くして」「難しくして」と言っても、見た目が複雑になるだけということでした。判断の基準を渡さないと、遊べるかどうかは誰も見ていません。

指示に入れたこと

地形は「先に正解の道を引く → その道が通らないすき間だけ塞ぐ」順で作ること
正解の道(跳ぶ高さ・着く高さ)を、生成した地形と一緒に持っておくこと
遊びのルールは MonoBehaviour から切り離し、テストから直接呼べるようにすること
1000種類の種で「正解の道をなぞれば生き残れる」検査を必ず一緒に書くこと
要素を1つ足すたびに、その検査をもう一度通すこと

最後の1行が効きました。溜め跳び・空中の天井・壁の幅の変化と、遊びの要素を足すたびにこの検査が落ち、そのたびに設計の穴が1つ見つかっています。足したときに落ちなかった要素は、ひとつもありませんでした。

まとめ

  • 理不尽な地形は、あとから弾くのではなく作られない手順にする。先に正解の道を引き、その道が通らないすき間だけを塞ぐ
  • 種を変えた総当たりの検査を、遊びの要素を足すたびに通す。このゲームでは 1000種で 5.93秒
  • 遊びのルールをエンジンから切り離しておくと、この検査が数秒で終わる
  • 「永遠に遊べない」「1プレイが目安の長さに収まる」も、数字で書けるならテストにできる
  • AI に渡すのは「面白くして」ではなく、合格の条件をテストの形で

できあがったゲームは、そのまま遊べます。

FAQ

よくある質問

自動生成のステージが理不尽になるのを防ぐには?

生成したあとに「クリアできるか」を判定して弾くより、先に正解の道を引いてから、その道に関係しないすき間だけを埋めるほうが確実です。理不尽な配置は「見つけて捨てる」のではなく、そもそも作られません。

1000種類も検査すると時間がかかりませんか?

この記事のゲームでは 5.93秒 でした。当たり判定だけを 1/120秒 刻みで回す計算なので、描画もエンジンも要りません。エンジンに依存しない形で書いておくことが条件です。

AI に地形の生成を書かせるとき、何を指示すればいいですか?

「難しくして」ではなく「正解の道を先に作り、その道を塞がないこと」「1000種類の種で確かめるテストを一緒に書くこと」を指示します。判断の基準をテストの形で渡さないと、AI は見た目だけ複雑にします。

上手い人が永遠に遊べてしまうのを防ぐには?

追ってくる危険の速さを高さに応じて上げ、地形が想定する登り速度をいつか追い抜くようにします。このゲームでは、機械が完璧に遊んだときの1プレイが 81秒(74〜88秒)に収まりました。

SOURCES

出典

  1. 01Edit mode and Play mode tests(Unity マニュアル)Unityエンジンを動かさずに実行できるテストの種類を確認

この記事は役に立ちましたか?

NEXT