アクションゲームやシューティングゲームで、当たり判定のすり抜け、という現象を聞いたことがある方もいらっしゃるでしょう。
これはゲームの作り方の問題で、2 つの物体がぶつかったかどうかを判定するとき、物体同士の軌道としては重なっていたにも関わらず、物体の移動速度が速すぎた、あるいは処理落ちしたため、物体同士が接触している瞬間が判定できず、すり抜けてしまった、という現象です。
今回は、ビートセイバーで、この当たり判定のすり抜けが発生するのか、見ていこうと思います。
ビートセイバーの当たり判定は、描画フレーム単位で処理が行われています。つまり、VR の HMD が 144Hz で動いていれば 1 秒間に 144 回、90Hz の HMD であれば 1 秒間に 90 回、判定が行われます。
環境によって若干差がでてしまいますが、一般的な手法ではあります。以降ではこの数字を使う部分があるので最初に触れておきました。
セイバーの当たり判定は、セイバー本体が接触しているか、で判定するのではなく
- セイバーの先端
- セイバーの末端 (柄部分は含まない)
- 1フレーム前 (過去) のセイバーの先端と末端の中央地点
この 3 点から求めた長方形を使って行われます。
下の図の赤い部分がノーツの当たり判定と重なっているとき、ノーツがカットされた、と判定されるわけですね。
この場合、セイバーに関しては、当たり判定のすり抜けはほぼ起こりません。セイバー本体ではなく、セイバーが移動した軌跡の部分が当たり判定になっているおかげで、当たり判定のない隙間がほとんどできないためです。
ノーツの当たり判定については下記に詳しくまとめていますが、結論としては
縦 50cm 横 80cm 奥行き 100cm (グッドカット用の大きいほうの当たり判定)
という大きさになっています。

今回はビートセイバーのノーツの当たり判定について書いてみようと思います。 ビートセイバーのノーツの当たり判定は、目に見えるノーツモデルの外側に大きい直方体と、内側に小さい立方体の二種類用意されています。 大きいほうの当たり判定は、セイバーとノーツが同じ色の場合のみに反応し、同色セイバーをこの部分に...
ただし、ノーツに関してはフレーム間での移動は考慮されていません。つまり、仮にノーツが 1 フレームの間に 10m 動いていたとしたら、ノーツの奥行 1m 分を除いた 9m の空間は当たり判定がない部分になり、セイバーの軌道がここを通っていたとしても空振りになってしまいます。これは問題になるのでしょうか?
ここでノーツ速度は実際どの程度なのか調べてみましょう。一般的な譜面では、NJS (Note Jump Speed) は上位のランク譜面でも 20 前半くらいで収まる程度に設定されています。
この NJS という数字は、ゲーム内で 1 秒間にノーツが何 m 動くかを表しています。ここでは仮に NJS 20 の譜面で考えてみます。1 秒間に 20m 動くということは、90Hz で動作する HMD の場合、20m を 90 で割って、1フレームあたり 0.22m = 22cm 動くことになります。ノーツの奥行き方向の当たり判定は 1m と、0.22m より十分に大きいので、フレーム間で当たり判定が抜けている部分はない、ということになりますね。
つまり、ノーツの当たり判定は、理論的にはすり抜けする可能性はあるけれど、通常はまったく問題ない、ということになります。
ビートセイバーでは、当たり判定のすり抜けは通常起こりません。至極普通な結論になってしまいましたが、きちんと作られている、ということで歓迎できますね。
・
・
・
・
・
これだけで終わってしまうのはなんなので…
通常起こらない、と書きましたが、通常ではない譜面ではすり抜けが発生することもあります。たとえば、この譜面…
この nyoom (bsr 52dd) という譜面は、NJS 200 が設定されています。つまり、1 秒間に 200m ノーツが動くので、ノーツの当たり判定が存在しない隙間ができてしまいます。
試しに簡単な mod を作って、下の青ノーツの中心位置を毎フレーム出力してみました。以下は、ノーツがプレーヤー付近 z = 0 に近づいたときの出力です。
time=1.21: pos=(-0.90, 0.68, 4.27)
time=1.22: pos=(-0.90, 0.68, 2.09)
time=1.23: pos=(-0.90, 0.68, -0.22)
time=1.24: pos=(-0.90, 0.68, -2.55)
1フレームごとに、ノーツ位置の z 軸が約 2.2m 変化しているのがわかると思います。1.22 秒の時点ではノーツはプレーヤーより 2.1m 離れたところに、1.23 秒の時点ではプレーヤー後方にいってしまっているので、1.225 秒の当たるタイミングでセイバーを左に振っていたとしても、当たり判定の隙間を通過して空振りしてしまうことなります。
なお、上記の数字はプレイのたびに変わります。1 秒間に 90 回描画する、という状況は同じでも、その 90 回中 1 回の描画が 1.220 秒のタイミングで行われるのか、1.221 秒のタイミングになるかは、そのときになってみないとわかりません。
ちなみにこの譜面、すり抜けを考慮しないとしても、セイバーを当てられるタイミングは 1 フレームしかないので、ぴったりそのタイミングに合わせてセイバーを振るのはなかなか難しいです。自信のある方はチャレンジしてみてください!
じつは昔のビートセイバーには、ノーツの当たり判定すり抜け対策のコードが存在していました。フレーム間の移動量分、奥行き方向の当たり判定を伸ばす形で、すり抜けが発生しないような処理が書かれています。
ただし、このコードは存在するだけで使われていないようでした。実際のゲーム中でそのコードが走ることはないので、昔のビートセイバーのほうが有利だった、ということもありません。そして最近のビートセイバーからは、その存在も消されてしまいました…。
実際のところ、NJS 200 なんて譜面は現実的ではありませんし、必要ない、と判断したのかもしれませんね。
前述した通り、ビートセイバーの場合、描画フレームに連動して当たり判定を行っているため、描画が処理落ちしている状態だと、当たり判定が行われる周期も下がってしまいます。
例えば、セイバーを振り下ろしてから振り上げる、という動作をとったとしても、振り下ろした瞬間が判定されていなければ、最悪、セイバーは上げたままだと判定されてしまいます。
また、処理落ちしている状態だと、ノーツの 1 フレーム間の移動距離も大きくなるため、すり抜けが発生する可能性もあります。
極端に重い壁譜面を遊んでいるとき、セイバーがノーツに当たりにくいと感じるのは、こういった要因が重なっています。
セイバーに関して、当たり判定のすり抜けは「ほぼ」起こらない、と書きましたが、その「ほぼ」の部分ついて…。
上で紹介したこの図からもう 1 フレーム進んだ状態を見てみましょう。
…先端部分にすこし隙間がありますね。ただノーツの当たり判定の大きさは十分に大きいため、ノーツ全体がここに入り込んでしまうことはなく、すり抜ける、というほどのことにはなりません。
ただし、セイバー先端がノーツに当たるかどうか、というタイミングで振っていたときは、この隙間のせいで空振りする状況も考えられます。どの程度、その状況が発生するかは微妙なところですが、絶対ないとは言えません。
フレームレートが高い HMD を使用することで、この隙間を小さくすることは可能です。例えば、セイバー速度 160km/h で振っていると仮定すると、フレームレートが 90fps の場合は 1 フレームあたりセイバー先端は 50cm 動きますが、144fps 動作の場合は 30cm になります。
図にするとこんな感じ。フレーム間のセイバー移動距離が小さくなると、隙間も小さくなるのがわかると思います。
つまり、これだけを考えると 144Hz 設定が可能な Valve Index が有利になりますが、実際のところ、Index 使用のランカーと、90Hz 動作の HMD を使用しているランカーで、明確に有利不利が出ているわけではないので、そこまでの違いはないのかな、とも思います。(そもそも Index はコントローラーが重いので、その点は不利な気もします…)
注)
カメラ mod やアバター mod、ほか負荷のある mod を使用している場合、Index の 144Hz 設定で動かすのは困難です。よほど PC の性能が高いか、アバターを軽く最適化しているか、カメラも最小限にとどめているか…、でないと 144Hz 設定は処理落ちしてしまって逆にマイナスになります。