This explanation is currently available in Japanese.
ひとことで
ある点からある方向へまっすぐ伸ばした「光線(レイ)」が、どの物体に、どこで、最初に当たるかを調べる処理です。銃弾の当たり判定、足元の地面探し、視線が壁にさえぎられるかの判定、マウスで指した物体の選択など、ゲームの中で最もよく使われる問い合わせの 1 つです。物体の形ごとに、光線との交点を式で求めます。
ゲームでの使いどころ
- 撃つ・選ぶ:弾がすぐ届く銃(ヒットスキャン)の当たり、画面をクリックした所にある物体の選択。
- 接地判定:キャラクターの足元から下へ短い光線を飛ばし、地面までの距離と傾き(法線)を得る。坂に足を合わせたり、空中かどうかを決めたりする。
- 視線・遮蔽:敵からプレイヤーが見えるか、音や光がさえぎられるか(環境クエリのテスト)。
- カメラ:三人称カメラがキャラクターとの間に壁を挟んだら、壁の手前まで寄せる。
しくみ
光線を ( が始点、 が向きの単位ベクトル、 が距離)と書き、形の式に代入して を求めます。
球(中心 、半径 ): は の 2 次方程式です。、、 として
根号の中が負なら当たりません。
軸に平行な箱(スラブ法):x・y・z の各軸について、光線が「箱の厚みの板」に入る時刻と出る時刻を求めます。3 つの入る時刻の最大が、3 つの出る時刻の最小以下なら当たりで、入る時刻の最大が当たった距離です。回転した箱は、光線を箱の座標系へ変換してから同じことをします。
いちばん近い当たり:光線上に複数の物体がある場合は、すべての交点の中で が最小のものが当たりです。物体が多い場合は、BVH などで調べる物体を絞ります。
反射:当たった点の法線 を使えば、跳ね返った向きは です。
実装のポイント
- 長さの上限:光線には必ず最大の距離を付けます。接地判定なら「足元からどれだけ下まで調べるか」がこの長さです。
- 自分自身に当たらない:キャラクターの体の中から飛ばすと、自分に当たります。調べる対象から自分を除く(レイヤーやマスク)か、始点を体の外に出します。
- 浮かせて飛ばし直す:反射や貫通で当たった点から飛ばし直すときは、法線方向にわずかにずらします。ずらさないと、数値の誤差で同じ面にまた当たります。
- 太さのある光線:細い光線は、物の角や隙間をすり抜けがちです。球や箱を光線に沿って動かす「形状キャスト(スフィアキャスト)」を使うと、太さのある判定になります(連続衝突判定と同じ考え方)。
つまずきやすい点
- 光線の向きが単位ベクトルでない:向きの長さが 1 でないと、 が距離にならず、上限の判定や式がずれます。
- 接地判定が途切れる:足元から調べる長さが短すぎると、速く下り坂を歩いたときに地面が届かない所まで下がり、一瞬「空中」と判定されます。坂を歩く速さに合わせて長さに余裕を持たせるか、接地していたら下へ吸い付ける処理を加えます。
- 裏から当たる:物体の中から飛ばした光線は、形によっては内側の面に当たったり、当たらなかったりします。始点が形の中にある場合の扱いを決めておきます。
デモで試すこと
- 「照準と跳弾」では、カーソルの方向へレーザーを撃ちます。光線上で最初に当たった物が赤く、その奥にあって当たらなかった物が黄色になります。
- 白い矢印は当たった点の法線です。「反射の回数」を増やすと、法線で反射しながら跳ね返っていきます。
- 「接地判定」では、キャラクターの腰から真下へ 3 本の光線を飛ばし、地面に届いた光線(緑)で足元の高さを決めます。白い矢印が坂の法線です。
- 「足元から下へ調べる長さ」を短くし、「歩く速さ」を上げると、下り坂で地面を見失って「空中」になり、「接地が途切れた回数」が増えます。