Collision & spatial queries

Ray Casting

レイキャスト

線と形状の交差から照準や接地を調べる。

1 / 10

Interactive demo

Preparing the demo…

Ray Casting

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

This explanation is currently available in Japanese.

ひとことで

ある点からある方向へまっすぐ伸ばした「光線(レイ)」が、どの物体に、どこで、最初に当たるかを調べる処理です。銃弾の当たり判定、足元の地面探し、視線が壁にさえぎられるかの判定、マウスで指した物体の選択など、ゲームの中で最もよく使われる問い合わせの 1 つです。物体の形ごとに、光線との交点を式で求めます。

ゲームでの使いどころ

  • 撃つ・選ぶ:弾がすぐ届く銃(ヒットスキャン)の当たり、画面をクリックした所にある物体の選択。
  • 接地判定:キャラクターの足元から下へ短い光線を飛ばし、地面までの距離と傾き(法線)を得る。坂に足を合わせたり、空中かどうかを決めたりする。
  • 視線・遮蔽:敵からプレイヤーが見えるか、音や光がさえぎられるか(環境クエリのテスト)。
  • カメラ:三人称カメラがキャラクターとの間に壁を挟んだら、壁の手前まで寄せる。

しくみ

光線を p(t)=o+t d\mathbf{p}(t) = \mathbf{o} + t\,\mathbf{d}(o\mathbf{o} が始点、d\mathbf{d} が向きの単位ベクトル、t≥0t \ge 0 が距離)と書き、形の式に代入して tt を求めます。

球(中心 c\mathbf{c}、半径 rr):∣o+td−c∣2=r2|\mathbf{o} + t\mathbf{d} - \mathbf{c}|^2 = r^2 は tt の 2 次方程式です。m=o−c\mathbf{m} = \mathbf{o} - \mathbf{c}、b=m⋅db = \mathbf{m}\cdot\mathbf{d}、c=∣m∣2−r2c = |\mathbf{m}|^2 - r^2 として

t=−b−b2−ct = -b - \sqrt{b^2 - c}

根号の中が負なら当たりません。

軸に平行な箱(スラブ法):x・y・z の各軸について、光線が「箱の厚みの板」に入る時刻と出る時刻を求めます。3 つの入る時刻の最大が、3 つの出る時刻の最小以下なら当たりで、入る時刻の最大が当たった距離です。回転した箱は、光線を箱の座標系へ変換してから同じことをします。

いちばん近い当たり:光線上に複数の物体がある場合は、すべての交点の中で tt が最小のものが当たりです。物体が多い場合は、BVH などで調べる物体を絞ります。

反射:当たった点の法線 n\mathbf{n} を使えば、跳ね返った向きは d′=d−2(d⋅n)n\mathbf{d}' = \mathbf{d} - 2(\mathbf{d}\cdot\mathbf{n})\mathbf{n} です。

実装のポイント

  • 長さの上限:光線には必ず最大の距離を付けます。接地判定なら「足元からどれだけ下まで調べるか」がこの長さです。
  • 自分自身に当たらない:キャラクターの体の中から飛ばすと、自分に当たります。調べる対象から自分を除く(レイヤーやマスク)か、始点を体の外に出します。
  • 浮かせて飛ばし直す:反射や貫通で当たった点から飛ばし直すときは、法線方向にわずかにずらします。ずらさないと、数値の誤差で同じ面にまた当たります。
  • 太さのある光線:細い光線は、物の角や隙間をすり抜けがちです。球や箱を光線に沿って動かす「形状キャスト(スフィアキャスト)」を使うと、太さのある判定になります(連続衝突判定と同じ考え方)。

つまずきやすい点

  • 光線の向きが単位ベクトルでない:向きの長さが 1 でないと、tt が距離にならず、上限の判定や式がずれます。
  • 接地判定が途切れる:足元から調べる長さが短すぎると、速く下り坂を歩いたときに地面が届かない所まで下がり、一瞬「空中」と判定されます。坂を歩く速さに合わせて長さに余裕を持たせるか、接地していたら下へ吸い付ける処理を加えます。
  • 裏から当たる:物体の中から飛ばした光線は、形によっては内側の面に当たったり、当たらなかったりします。始点が形の中にある場合の扱いを決めておきます。

デモで試すこと

  1. 「照準と跳弾」では、カーソルの方向へレーザーを撃ちます。光線上で最初に当たった物が赤く、その奥にあって当たらなかった物が黄色になります。
  2. 白い矢印は当たった点の法線です。「反射の回数」を増やすと、法線で反射しながら跳ね返っていきます。
  3. 「接地判定」では、キャラクターの腰から真下へ 3 本の光線を飛ばし、地面に届いた光線(緑)で足元の高さを決めます。白い矢印が坂の法線です。
  4. 「足元から下へ調べる長さ」を短くし、「歩く速さ」を上げると、下り坂で地面を見失って「空中」になり、「接地が途切れた回数」が増えます。

References

Box2D Collision ↗

A general reference for this subcategory.