Pathfinding & decisions

Environment Query / EQS

環境クエリ

周囲の候補地点を評価して隠れ場所を選ぶ。

10 / 10

Interactive demo

Preparing the demo…

Environment Query / EQS

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

「どこに隠れるか」「どこから撃つか」のような場所選びを、周りに候補地点をたくさん並べ、テストで絞り込み、得点の高い所を選ぶことで行う方法です。Unreal Engine の Environment Query System(EQS)が有名です。「敵から見えない」「自分から近い」「敵から適度に離れている」といったテストを部品として組み合わせるだけで、状況に合った場所を毎回選べます。

ゲームでの使いどころ

  • 隠れ場所・物陰:撃ち合いの最中に、敵から射線が通らず、自分から近い場所へ移る。
  • 射撃位置・回り込み:敵が見えて、しかも味方と重ならない位置。敵の背後に回り込める位置。
  • 逃げ先・待ち伏せ:敵から遠く、出口に近い場所。プレイヤーが通りそうで、見つかりにくい場所。
  • アイテムや敵の出現位置:プレイヤーから見えず、近すぎない場所に敵を出す。

しくみ

クエリは 3 段階で動きます。

  1. 生成(ジェネレーター):候補の地点を作ります。自分の周りの格子、円周上の点、ナビメッシュ上の点、近くの物陰の一覧など。
  2. テスト:各候補にテストをかけます。テストには 2 種類あります。
    • ふるい(フィルター):条件を満たさない候補を捨てます(敵から見える、たどり着けない)。
    • 得点(スコア):0〜1 の点数を付けます(近いほど高い、敵との距離が 4 m に近いほど高い)。
  3. 選択:得点の重み付きの合計が最も高い候補を選びます(上位からランダムに選ぶこともあります)。
得点=∑kwk sk∑kwk\text{得点} = \frac{\sum_k w_k\, s_k}{\sum_k w_k}

「敵から見えない」は、敵の目の位置から候補までレイキャストして、壁に当たるかで調べます。「自分から近い」は、直線距離より、経路の長さ(ダイクストラ法で一度に求められる)を使う方が正確です。壁の向こうの点は、直線では近くても回り込むと遠いからです。

実装のポイント

  • 軽いテストを先に:レイキャストや経路探索は重いので、距離のような軽いテストで先に候補を減らします。
  • 数フレームに分ける:候補が多いクエリは、1 フレームで全部評価せず、数フレームに分けます。結果が出るまでは前の行動を続けます。
  • やり直しの頻度:敵が動くと結果が変わるので、一定間隔(0.3〜1 秒)でやり直します。やり直すたびに行き先が小さく変わってふらつくなら、今の行き先に少し加点して、よほど良い場所でない限り変えないようにします。
  • 候補の並べ方:格子は偏りなく並べやすく、ポアソンディスク分布を使うと、少ない数でもまんべんなく調べられます。

つまずきやすい点

  • 得点の重みの調整:テストが増えると、重みの組み合わせで結果が大きく変わります。得点ごとに色で表示できるデバッグ表示を用意すると、調整がずっと楽になります(デモの「色で見る得点」)。
  • 地面の高さ:レイキャストを地面の高さで飛ばすと、低い柵でも見えないことになります。目の高さ、体の中心など、テストの意図に合った高さで調べます。
  • 全員が同じ場所を選ぶ:同じクエリを複数の敵が使うと、全員が同じ最高点の場所へ殺到します。ほかの敵が選んだ場所の近くを減点するテストを足します。

デモで試すこと

  1. 青い兵士の周りに候補点が並び、敵(緑の球)から見える点は灰色で捨てられます。残った点は得点で色分けされ、白い輪が選ばれた地点です。
  2. 緑の球をドラッグすると、見える範囲が変わり、兵士は次の物陰へ走ります。左下で、兵士が「隠れている」かを確かめてください。
  3. 「ふるい:敵から見えない」を切ると、敵から丸見えの場所でも得点が高ければ選んでしまいます。
  4. 「色で見る得点」で、近さと敵との距離の得点を別々に見られます。どちらかの得点を切ると、選ばれる場所の傾向が変わります。

References

Red Blob Games — A* Introduction ↗

A general reference for this subcategory.