読者です 読者をやめる 読者になる 読者になる

趣味プログラマによるOSS開発日誌

趣味で作っているOSSソフトウェアの紹介や関連技術の紹介、楽曲製作、Webデザイン勉強状況を紹介します。

レーシングゲームにおける逆走判定

ほとんどのレーシングゲームでは、逆走した時に逆走したことを示すメッセージが表示される。
逆走したことのメッセージが存在しないと、
プレイヤーが逆走に気がつかないまま逆走を続けてしまう可能性があり、非常に不親切である。

現在作成しているアプリでも同じ機能をつける必要があり、
逆走判定を行う必要が出てきたため、逆走判定のアルゴリズムをまとめてみた。
候補となるアルゴリズムは、以下の3つである。

1. 進行方向を示すマップを作成し、現在地の進行方向と自身の進行方向を比較

 [アルゴリズム]
  2Dまたは、3Dで高さ成分をあまり考慮する必要がない場合は、
  2次元配列等を利用して、各場所における進行方向を持つマップを作成すればよい。
  3Dで高さが大きく変更される場合(フライトレーシング等)は、
  3次元配列を用いて3D空間上を表現すればよい。

 [利点]
  それぞれの場所で進むべき進行方向の判定が行えるため、
  逆走した瞬間に検知可能である。

 [欠点]
  判定の精度を細かくしたい場合、進行方向を指定する場所が増え、
  進行方向の入力の手間が非常にかかってしまう。
  特に3D空間の場合、すべての部分に進行方向を入力するのは非現実的である。

2. チェックポイントを設置し、チェックポイントの通過方向から判定

 [アルゴリズム]
  コースを複数のセグメント(区分)に分割して、
  セグメントが切り替わる部分にチェックポイント(判定ポイント)を置いておく。
  それぞれのチェックポイントは、通過点であることを考えると、
  2Dでは進行方向と垂直な直線、3Dでは進行方向と直角に交差する板ポリが良い。
  設定したチェックポイントを通過した時、チェックポイントの通過方向から、
  逆走の判定が可能である。
  手前から奥の場合は順方向、奥から手前の場合は逆方向と判断すればよい。
  
 [利点]
  3Dへの対応が簡単である。
  また、複雑な地形に対しても、板ポリや直線を向きに気をつけながら設置するだけで良いので、
  1.に比べて、かかる手間が少ない。
  判定の精度を細かくしたい場合にも上記の利点が当てはまる。

 [欠点]
  チェックポイントの通過が判定のタイミングとなるため、
  チェックポイントを通過しない限り、判定することができない。
  チェックポイント間の距離が長いと、プレイヤーはなかなか逆走に気がつけない。

3. チェックポイントを設置し、次に進むべきチェックポイントと、進行方向を比較して判定

 [アルゴリズム]
  2.と同様に複数のセグメントに分割し、セグメントが切り替わる部分にチェックポイントを置くか、
  ルートに沿ってWayPointを置く。
  どちらの場合にも、粒度が小さい場合には正しい判定が行えないため、設置方法には気をつける必要がある。
  特に直線なら粒度が低くても問題ないが、カーブが急な所では粒度を高くしなくてはならない。
  逆走判定は、次に進むべきチェックポイントと、一番最後に通過した(接近した)チェックポイントから進行方向を割り出し、
  プレイヤーの進行方向との内積を取ることによって行う。
  例えば、以下の条件を満たす場合に逆走したと判断する。
  
  ( c1 - c0 ) ・p < r * | c1 - c0 | * | p |
  
  c0: 一番最後に通過したチェックポイントの位置
  c1: 次のチェックポイントの位置
  p: プレイヤーの進行方向
  r: 逆走とみなす範囲(1.0から-1.0の間)
  
  rは1.0から-1.0の値を取り、値が大きいほど逆走判定が大きくなる。
  1.0では、いかなる方向でも逆走と判定し、-1.0では逆走と判定されない。
  そのため、基本的には0.0(後ろ半分を逆走と判定)以下にする。
  
 [利点]
  2.と同様、3Dへの対応が簡単である。
  常に逆走判定が行える。
  
 [欠点]
  チェックポイントの置き方が良くないと、誤判定する可能性がある。
  このため、チェックポイントの置き方を十分考慮する必要があり、手間がかかる。


理想的には3.が良いのだが、2.では生じなかった誤判定が起こりやすかったため、
現在作成しているアプリでは2.を採用することにした。
加えて3.は、チェックポイントを慎重に設置する必要であるため、
Unity上ではなかなか面倒だと感じた。