Amazon10/19まで!プライム感謝祭開催中!セール会場へ

UnityのRaycastの使い方|3Dの当たり判定と当たらない原因

UnityのRaycast / 当たり判定とレイヤーを確認

UnityのRaycastは、ある位置から特定の方向へ見えない線を飛ばし、Colliderに当たるかを調べる機能です。前方の壁を調べる、照準の先にある物を判定する、といった処理に使えます。

3DではPhysics.Raycast、2DではPhysics2D.Raycastを使います。見た目が平面的なゲームでも、使用しているColliderが3D用ならPhysics側です。最初に、この組み合わせを確認してください。

目次

Raycastに必要な4つの情報

情報意味例
origin線を飛ばす開始位置カメラやセンサーの位置
direction線を飛ばす方向オブジェクトの前方
maxDistance判定する距離前方10単位
layerMask判定対象のレイヤー壁や操作できる物だけ

directionには、目的地のワールド座標をそのまま入れるのではなく、開始位置から見た方向を渡します。ある地点を狙うならtargetPosition – originから方向を求めます。距離を有限にしておくと、想定外の遠い物まで判定するのを避けやすくなります。

前方のColliderを調べるコード

ForwardRayExample.csという名前で保存し、空のGameObjectに追加します。Input Systemには依存しない例で、再生中に前方の判定結果をInspectorへ表示します。

using UnityEngine;

public class ForwardRayExample : MonoBehaviour
{
    [SerializeField] private float distance = 10f;
    [SerializeField] private LayerMask targetLayers = Physics.DefaultRaycastLayers;
    [SerializeField] private string hitObjectName;

    private void Update()
    {
        Vector3 origin = transform.position;
        Vector3 direction = transform.forward;
        float length = Mathf.Max(0f, distance);
        bool found = Physics.Raycast(
            origin, direction, out RaycastHit hit, length,
            targetLayers, QueryTriggerInteraction.Ignore);

        hitObjectName = found ? hit.collider.name : "なし";
        float drawLength = found ? hit.distance : length;
        Debug.DrawRay(origin, direction * drawLength,
            found ? Color.green : Color.red);
    }
}

Updateで調べるたびにConsoleへログを出すと、判定結果が大量に並びます。この例では、Hit Object Nameの表示だけを更新します。Debug.DrawRayは確認用の線であり、製品内のレーザー表現を描画する機能ではありません。

Cubeを置いて動作を確認する

  1. 空のGameObjectを原点に置き、回転を0にします。
  2. Cubeを位置(0, 0, 5)付近に置き、Box Colliderを有効にします。
  3. 空のGameObjectへスクリプトを追加し、Distanceを10にします。
  4. 再生して、Hit Object NameにCubeの名前が出るか確認します。
  5. SceneビューのGizmosを有効にし、線の方向を見ます。

次にCubeを横へ移動し、判定が「なし」へ変わるかを確かめます。さらにDistanceを2にすると、前方5付近のCubeには届かなくなります。方向、距離、Colliderの関係を1つずつ変えると、コードの意味を追いやすくなります。

LayerMaskはレイヤー番号そのものではない

判定対象を絞るときは、InspectorのTarget Layersでレイヤーを選びます。コードで指定するならLayerMask.GetMask(“名前”)などを使います。レイヤー番号の8と、8番レイヤーを表すビットマスクは同じ値ではありません。

この例はTriggerを無視する設定です。Triggerへも当てたいなら、QueryTriggerInteraction.Collideなど、用途に合う指定へ変更します。基本の引数、返り値、Triggerの扱いはUnity 6のPhysics.Raycastリファレンスで確認できます。

当たらないときに確認する順番

  • Mesh Rendererだけでなく、Colliderが付いているか。
  • ColliderとGameObjectが有効か。
  • 2D用と3D用の物理APIを混ぜていないか。
  • 開始位置と前方向が意図した位置・向きか。
  • 判定距離とLayerMaskが対象を含んでいるか。
  • Triggerを無視する設定になっていないか。

開始点がColliderの内部にある場合、そのColliderを検出できないケースにも注意します。自分自身の中心から線を出して外殻を調べようとするより、開始位置を外へ置くか、目的に合う別の判定方法を検討します。

線ではなく太さが必要な判定は別に考える

細い線1本の判定では、キャラクターの幅や足元全体を表現できません。前進できる隙間を調べたいなら、SphereCastやCapsuleCastなど、形状を持つ判定が適する場合があります。

まずRaycastで位置・方向・距離を理解し、その後で用途に合う形へ広げると整理しやすくなります。今回のサンプルも、物理的に移動を止める処理は含まず、前方に何があるかを確認するためのものです。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

Unityのおすすめ書籍

開発PCの選び方

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次