UnityのRaycastHitには何が入っている? hit.point・distance・normal・colliderを理解しよう
前回は、マウスでクリックした3Dオブジェクトを取得するために、次のようなコードを書きました。
Ray ray =
Camera.main.ScreenPointToRay(
Mouse.current.position.value
);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.Log(hit.collider.gameObject.name);
}
この中に、
RaycastHit hit;
というコードがあります。
前回は、
Rayが当たったときの情報を受け取る箱
くらいに考えました。
今回は、この hit の中に実際にどんな情報が入っているのかを見ていきましょう。

RaycastHitは「当たった結果のセット」
Raycastをすると、
Rayを飛ばす
↓
Colliderに当たる
だけではありません。
Unityは、そのときの情報をいろいろ教えてくれます。
たとえば、
何に当たった?
どこに当たった?
どのくらい離れていた?
どちらを向いた面に当たった?
といった情報です。
それをまとめて受け取るのが、
RaycastHit hit;
です。
イメージとしては、
hit
├ collider
├ point
├ distance
├ normal
├ rigidbody
├ transform
└ その他の情報
のようなデータのまとまりです。
今回は特に重要な、
hit.collider
hit.point
hit.distance
hit.normal
の4つを見ていきます。
hit.collider ― 何に当たった?
まず一番分かりやすいのが、
hit.collider
です。
これは、
Rayが当たったCollider
を表します。
たとえばCubeに Box Collider が付いていて、そこにRayが当たった場合、
hit.collider
には、その Box Collider が入ります。
Unity 6の公式リファレンスでも collider は「ヒットしたCollider」と定義されています。

GameObjectまで取得する
通常はColliderそのものより、
そのColliderが付いているGameObject
を知りたいことが多いでしょう。
そこで、
hit.collider.gameObject
と書きます。
たとえば、
GameObject obj =
hit.collider.gameObject;
Debug.Log(obj.name);
とすれば、
Cube
など、クリックしたGameObjectの名前を表示できます。
処理の流れは、
hit
↓
collider
↓
gameObject
です。
hit.point ― どこに当たった?
次は、
hit.point
です。
これは、
RayがColliderに当たった位置
を表します。
型は、
Vector3
です。
つまり、
X
Y
Z
の3つの座標を持っています。
Unity公式では、hit.point は「RayがColliderに当たったワールド空間上の位置」とされています。

実際に表示してみる
Debug.Log(hit.point);
としてみましょう。
たとえば、
(2.3, 1.1, 5.7)
のように表示されます。
これは、
GameObjectの中心位置
ではありません。
重要なのは、
Rayが実際に表面へぶつかった位置
だということです。
Cubeの中心とは違う
たとえばCubeのTransform.positionが、
(0, 0, 5)
だったとします。
しかし、RayがCubeの右上あたりに当たれば、
hit.point
は、
(0.4, 0.3, 4.5)
などになる可能性があります。
つまり、
transform.position
は、
GameObjectの基準位置
で、
hit.point
は、
Rayが実際に当たった場所
です。
この違いは非常に重要です。
hit.pointは何に使える?
たとえば、
クリックした位置にエフェクトを出す
銃弾が当たった位置に弾痕を作る
地面をクリックした場所へキャラクターを移動する
当たった位置にパーティクルを発生させる
といった処理に使えます。
たとえば、
Debug.DrawLine(
ray.origin,
hit.point,
Color.red
);
とすれば、
Rayの開始位置から実際に当たった位置までを可視化することもできます。
hit.distance ― どのくらい離れていた?
次は、
hit.distance
です。
これは、
Rayの原点から、Rayが当たった位置までの距離
を表します。
Unity 6の公式リファレンスでも、Rayの場合の distance は「Rayの原点から衝突点までの距離」とされています。
型は、
float
です。

表示してみる
Debug.Log(hit.distance);
たとえば、
8.52
と表示されたら、
Rayの開始位置から当たった場所までが、
8.52 Unity units
離れているということです。
一般的なUnityの3D空間では、1 Unity unitを1mとして扱う設計が多いので、
約8.52m
として扱うゲームもあります。
ただし、Unityが「1 unitは必ず1m」と強制しているわけではなく、ゲーム側のスケール設計によります。
pointとの関係
hit.point と hit.distance は似ていますが、意味が違います。
hit.point
は、
どこに当たったか
です。
hit.distance
は、
そこまでどのくらい離れているか
です。
たとえば、
Camera ●──────────────× Cube
↑
hit.point
この線の長さが、
hit.distance
です。
距離によって処理を変える
たとえば、
if (hit.distance < 3f)
{
Debug.Log("近くのオブジェクトです");
}
とすれば、
近くにあるオブジェクトだけを操作することもできます。
たとえば、
3m以内ならドアを開けられる
2m以内ならアイテムを拾える
10m以内なら敵を攻撃できる
といった処理につながります。
hit.normal ― 当たった面はどちらを向いている?
4つの中で少し難しいのが、
hit.normal
です。
normal は、
Rayが当たった面の法線ベクトル
です。
Unity公式でも、normal は「Rayがヒットしたサーフェスの法線」とされています。

法線とは?
難しく考える必要はありません。
法線とは、
面に対して垂直に外向きへ伸びている方向
です。
たとえば、床なら、
↑ normal
|
──────────── 床
となります。
通常の水平な床なら、
hit.normal
は、おおよそ、
(0, 1, 0)
になります。
つまり、
上方向
です。
壁ならnormalは横を向く
たとえば、右向きの面にRayが当たった場合、
壁
│ →
│ normal
│
のようになります。
面の方向によって、
hit.normal
も変わります。
そのため、
床なのか
壁なのか
斜面なのか
を判断するときにも利用できます。
normalは何に使える?
たとえば銃弾が壁に当たったとします。
弾痕の画像をただ配置するだけでは、
斜めの壁では向きがおかしくなるかもしれません。
そこで、
hit.normal
を利用すれば、
壁の面と同じ方向を向く
ように弾痕やエフェクトを配置できます。
ほかにも、
爆発エフェクトの向きを決める
地面の傾きを調べる
反射方向を求める
接触面にオブジェクトを沿わせる
といった処理につながります。

4つをまとめて表示してみよう
では、前回のクリック処理に、
collider
point
distance
normal
を追加してみましょう。
using UnityEngine;
using UnityEngine.InputSystem;
public class RaycastHitTest : MonoBehaviour
{
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
Ray ray =
Camera.main.ScreenPointToRay(
Mouse.current.position.value
);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.Log(
"Collider : " +
hit.collider.name
);
Debug.Log(
"Point : " +
hit.point
);
Debug.Log(
"Distance : " +
hit.distance
);
Debug.Log(
"Normal : " +
hit.normal
);
}
}
}
}
Cubeをクリックすると、Consoleにはたとえば、
Collider : Cube
Point : (0.42, 0.18, 4.50)
Distance : 9.53
Normal : (0.00, 0.00, -1.00)
のような情報が表示されます。

1回のRaycastでいろいろ分かる
ここで大切なのは、
Physics.Raycast(ray, out hit)
を実行すると、
単に、
当たった
だけではなく、
何に当たったのか
どこに当たったのか
どのくらい離れているのか
その面はどちらを向いているのか
という情報まで取得できることです。
つまり、
RaycastHit hit
は、
Raycastの結果報告書
のようなものだと考えると分かりやすいでしょう。
図にするとこうなる
Raycastの結果を図にすると、次のような関係です。
↑
│ hit.normal
│
Camera ●───────────────×│ Cube
<---------------> │
hit.distance │
↑
hit.point
当たったCollider
↓
hit.collider
これを見ると、
hit.collider
は、
何に当たったか
hit.point
は、
どこに当たったか
hit.distance
は、
そこまでどのくらい離れているか
hit.normal
は、
当たった面がどちらを向いているか
という違いが分かります。
RaycastHitはstruct
ここで少しだけC#の知識につなげてみましょう。
RaycastHit は、
class
ではなく、
struct
です。
Unityの公式リファレンスでも、
struct in UnityEngine
とされています。
つまり、
RaycastHit hit;
では、RaycastHit という構造体型の変数を用意しています。
その中に、
Collider
Vector3 point
float distance
Vector3 normal
など、複数の情報がまとめられています。
初心者の段階では、
Raycastの結果をひとまとめにするデータ型
と考えておけば十分です。
out hitの意味も見えてくる
ここまで分かると、
Physics.Raycast(ray, out hit)
の意味も以前より分かりやすくなります。
これは、
Rayを飛ばしてください
↓
当たったら
↓
結果の詳しい情報を
hitに入れてください
ということです。
そして、その後で、
hit.collider
hit.point
hit.distance
hit.normal
として情報を取り出しているわけです。
まとめ
RaycastHit hit には、Raycastによって得られたさまざまな情報が入ります。
特に最初に覚えておきたいのは、この4つです。
| プロパティ | 分かること |
|---|---|
hit.collider |
何に当たったか |
hit.point |
どこに当たったか |
hit.distance |
そこまでの距離 |
hit.normal |
当たった面の向き |
一言で整理すると、
collider → 何?
point → どこ?
distance → どのくらい?
normal → どっち向き?
です。
前回までの流れも含めると、
Camera.main
↓
ScreenPointToRay()
↓
Ray
↓
Physics.Raycast()
↓
RaycastHit
├ collider
├ point
├ distance
└ normal
となります。
RaycastHit を理解すると、Raycastは単なる「当たったかどうかの判定」ではなく、
3D空間の情報を調べるための非常に便利な仕組み
だということが見えてきます。









ディスカッション
コメント一覧
まだ、コメントがありません