UnityのRaycastは、始点から指定方向へ線を伸ばし、途中にあるColliderを調べる機能です。Physics.Raycastで当たった相手を取得し、hit.distanceで距離を測れます。見えない線を確認するときはDebug.DrawRayを使いましょう。

まずは前方に1本飛ばす例で、判定・距離・可視化をまとめて確認します。後半では、当たらないときの確認方法と、3本/360度に飛ばす例を紹介します。対象は3DのPhysics.Raycastです。

RaycastとColliderの関係

Colliderは当たり判定に使う「形」、Raycastはその形に線が交わるかを調べる「処理」です。相手にBoxColliderなどが必要ですが、Raycastで検出するだけならRigidbodyは必須ではありません。衝突イベントの条件とは分けて考えましょう。

Colliderの種類や設定は、Colliderの使い方で解説しています。足元の地面を調べる、照準の先にある物体を調べる、といった場面にRaycastを使えます。

前方の物体を検出し、距離を取得する

Cubeを2つ配置する

Hierarchyで右クリックし、3D Object → Cubeから2つ作成します。動かさずに試すなら、Rigidbodyは追加しなくて大丈夫です。次の配置なら、左のCubeの前方(ローカルZ方向)が右のCubeを向きます。

設定Rayを出すCube検出するCube
名前RayOriginTarget
Position(X, Y, Z)(-2, 1, 0)(0, 1, 0)
Rotation(X, Y, Z)(0, 90, 0)(0, 0, 0)
Scale(1, 1, 1)(1, 1, 1)
BoxCollider付いたままでOK有効・Is Triggerはオフ
Raycastの発射側と検出対象のCubeを配置したUnity画面
2つのCubeを使う配置例。試すときの座標は上の表を参考にしてください。

Physics.RaycastとRaycastHitのコード

ForwardRaycast.csを作成し、次のコードを保存してRayOriginにアタッチします。再生すると、前方5ユニットまでを判定し、当たった相手の名前と距離をConsoleへ出力します。SceneビューのGizmosもオンにしてください。

using UnityEngine;

public class ForwardRaycast : MonoBehaviour
{
    [SerializeField] private float rayDistance = 5f;

    private void Update()
    {
        Ray ray = new Ray(transform.position, transform.forward);
        bool hasHit = Physics.Raycast(ray, out RaycastHit hit, rayDistance);

        // 判定する距離全体を赤い線で表示
        Debug.DrawRay(ray.origin, ray.direction * rayDistance, Color.red);

        if (hasHit)
        {
            Debug.Log($"相手: {hit.collider.name} / 距離: {hit.distance:F2}");
        }
    }
}

Ray構造体には始点と方向をまとめます。Physics.Raycastの戻り値は「当たったかどうか」のbool値です。out RaycastHit hitは結果を受け取る変数を用意する書き方で、hitの情報はtrueになったときだけ使います。この書き方では、線上で最も近い対象の情報を取得します。

値分かること
hit.collider当たったCollider。名前はhit.collider.nameで取得
hit.distance始点から当たった位置までの距離
hit.point当たった位置のワールド座標
hit.normal当たった面の法線(面に垂直な向き)

この配置では、始点からTargetの中心までは2ユニットですが、手前の面までは1.5ユニットです。hit.distanceは中心間の距離ではありません。Consoleには当たっている間ログが出続けるので、確認後はDebug.Logを外して使いましょう。

当たり判定と距離をConsoleで確認する実演。

Debug.DrawRayでRayを可視化する

上のコードでは、判定する方向と距離を赤い線で描いています。Debug.DrawRayの第2引数は「方向×表示する長さ」で、終点の座標ではありません。Raycastによる判定と、線の描画は別の処理です。

線が見えないときは、再生中か、SceneビューのGizmosがオンかを確認します。GameビューにもGizmosをオンにすれば表示できます。ゲーム内のレーザーなど、プレイヤーに見せる線にはLineRendererなどを使います。

表示時間を省略すると線は1フレームだけ描かれるため、この例ではUpdateから毎フレーム呼んでいます。物体に隠れる場合は、確認用に第5引数のdepthTestをfalseにすると見つけやすくなります。

Debug.DrawRay(ray.origin, ray.direction * rayDistance, Color.red, 0f, false);
Sceneビューで赤いRayと対象の位置関係を確認する実演。

Raycastが当たらないときの確認ポイント

確認する場所見直すこと
Collider対象に3DのColliderがあり、有効になっているか。対象GameObjectもアクティブか
方向と距離transform.forwardは物体の向きに追従する。線が対象まで届くかDebug.DrawRayで確認
始点3DのRaycastでは、始点を内側に置いたCollider自身は検出されない。対象の外から飛ばす
LayerMask対象のLayerが判定に含まれるか。既定ではIgnore Raycastレイヤーは対象外
Is TriggerTriggerを無視する設定になっていないか。必要ならQueryTriggerInteraction.Collideを指定
2Dとの違いBoxCollider2DなどはPhysics2D.Raycastで調べる。3D用とはAPIも判定対象も別

LayerとTriggerを指定する場合

特定のLayerだけ調べたい場合は、ForwardRaycastクラスのrayDistanceの下に次のフィールドを追加します。InspectorのHit Layersで対象Layerを選び、Physics.Raycastの行を次のように置き換えてください。この例ではTriggerを無視します。

[SerializeField] private LayerMask hitLayers = Physics.DefaultRaycastLayers;
bool hasHit = Physics.Raycast(ray, out RaycastHit hit, rayDistance,
    hitLayers, QueryTriggerInteraction.Ignore);

Triggerも調べるならIgnoreをCollideに変えます。UseGlobalはPhysics設定に従います。LayerMaskはLayer番号そのものではなく、対象Layerの組み合わせを表す値です。Inspectorで選ぶと取り違えを防げます。

Rayを3本飛ばす:前・右斜め・左斜め

ThreeRays.csとして保存し、発射側にアタッチします。1本の例と同時に動かす必要はないので、ForwardRaycastは無効にしてください。前方に加え、左右45度の方向も調べます。ラベルを付けると、どの線が当たったかをログで区別できます。

using UnityEngine;

public class ThreeRays : MonoBehaviour
{
    [SerializeField] private float rayDistance = 5f;

    private void Update()
    {
        Cast("Forward", transform.forward);
        Cast("Right", (transform.forward + transform.right).normalized);
        Cast("Left", (transform.forward - transform.right).normalized);
    }

    private void Cast(string label, Vector3 direction)
    {
        if (Physics.Raycast(transform.position, direction,
            out RaycastHit hit, rayDistance))
        {
            Debug.Log($"{label}: {hit.collider.name}");
        }

        Debug.DrawRay(transform.position, direction * rayDistance, Color.red);
    }
}

斜め方向は、前と右(または左)を足してnormalizedで正規化します。詳しくはVector3の加算・正規化の使い方を参照してください。

前方と左右斜めの3本で、対象に当たる方向を調べる実演。

Rayを360度に飛ばす:レーダー風の判定

RadialRays.csを作成し、ほかの例を無効にして発射側へアタッチします。ワールドのXZ平面に、36本なら10度間隔でRayを飛ばします。発射側のX・Z回転が変わっても、この例の線は水平に広がります。

using UnityEngine;

public class RadialRays : MonoBehaviour
{
    [SerializeField] private float rayDistance = 10f;
    [SerializeField, Min(1)] private int rayCount = 36;

    private void Update()
    {
        for (int i = 0; i < rayCount; i++)
        {
            float angle = i * 360f / rayCount;
            // ワールドの水平面(XZ平面)に広げる
            Vector3 direction = Quaternion.Euler(0f, angle, 0f) * Vector3.forward;

            if (Physics.Raycast(transform.position, direction,
                out RaycastHit hit, rayDistance))
            {
                Debug.Log($"Ray[{i}] 角度 {angle:F0}°: {hit.collider.name}");
            }

            Debug.DrawRay(transform.position, direction * rayDistance, Color.cyan);
        }
    }
}
周囲へ放射状にRayを飛ばす実演。

Rayは細い線なので、線と線の間にある小さな物体は見逃します。周囲の範囲内にある物体を拾うならPhysics.OverlapSphere、太さを持たせて調べるならPhysics.SphereCastなど、目的に合う判定を選びましょう。大量のRayや毎フレームのログは負荷にもつながります。

まとめ

Raycastは、Colliderに向けて始点・方向・距離を指定するのが基本です。まず1本の線をDebug.DrawRayで見えるようにすると、向きや距離の間違いを見つけやすくなります。判定できたらhitの情報を使い、必要に応じてLayerの絞り込みや複数方向へ広げてみてください。

参考資料

仕様はUnity 6.0の公式資料で確認しています。Physics.Raycast / RaycastHit / Debug.DrawRay / Physics2D.Raycast