UnityでのRaycastを使用した衝突検知チュートリアル

Physics.Raycast は、指定した方向に「レイ」を飛ばして、その途中に何があるかを検出する手法です。Unityのゲーム開発では、例えばプレイヤーが前方にある敵や障害物を検知したり、銃の射撃をシミュレートするなど、さまざまなシーンで利用できます。このチュートリアルでは、Physics.Raycast の基本的な使い方を学びます。

Raycastとは

Raycastは、指定された位置から特定の方向に見えない「線」を飛ばし、その線に当たったオブジェクトの情報を取得するための手段です。この「線」はレイと呼ばれ、物理エンジンを使ってその経路上にあるオブジェクトを検知します。衝突が発生すると、どのオブジェクトに当たったかを知ることができます。

基本的なRaycastの使い方

UnityでRaycastを使うためには、Physics.Raycast メソッドを使用します。以下は、基本的なRaycastの使用例です。

using UnityEngine;

public class RaycastExample : MonoBehaviour
{
    void Update()
    {
        // Rayをプレイヤーの前方に飛ばす
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;

        // レイキャストを実行して、何かに当たったかを確認
        if (Physics.Raycast(ray, out hit))
        {
            Debug.Log("Hit object: " + hit.collider.name);
        }
    }
}

説明

  • Ray ray = new Ray(transform.position, transform.forward);: プレイヤーの現在位置から前方に向かってレイを飛ばす設定です。
  • RaycastHit hit;: レイが当たったオブジェクトの情報を格納する変数です。
  • Physics.Raycast(ray, out hit): Raycastを実行し、オブジェクトに当たったかどうかを確認します。当たった場合は hit に情報が格納されます。

Physics.RaycastAll を使用することで、レイキャストが複数のオブジェクトにヒットした場合にそれらを検出することができます。以下に具体的な方法とサンプルコードを示します。

Physics.RaycastAll を使用した複数ヒットの検出

Physics.RaycastAll は、レイがヒットしたすべてのオブジェクトに対する情報を RaycastHit の配列として返します。これにより、一度のレイキャストで複数のオブジェクトを検出することが可能です。

サンプルコード

// レイを作成(例としてカメラの中心から前方に発射)
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));

// レイキャストを実行して、ヒットしたすべてのオブジェクトを取得
RaycastHit[] hits = Physics.RaycastAll(ray);

foreach (RaycastHit hit in hits)
{
    Debug.Log("Hit object: " + hit.collider.name);
}

詳細な説明

  • レイの作成:
    • Camera.main.ScreenPointToRay を使用して、スクリーン上の特定のポイント(ここでは画面の中心)から発射されるレイを作成します。
  • Physics.RaycastAll の使用:
    • Physics.RaycastAll(ray) は、指定したレイにヒットしたすべてのオブジェクトを検出し、RaycastHit の配列として返します。
    • オプションで、最大距離やレイヤーマスクを指定することも可能です。
      csharp float maxDistance = 100f; int layerMask = LayerMask.GetMask("Default", "Interactable"); // 例: "Default" と "Interactable" レイヤーのみ検出 RaycastHit[] hits = Physics.RaycastAll(ray, maxDistance, layerMask);
  • ヒットしたオブジェクトの処理:
    • 取得した RaycastHit の配列を foreach ループで回し、各ヒットオブジェクトの情報(ここではオブジェクト名)をログに出力します。

パフォーマンスの考慮

  • 大量のオブジェクトが存在する場合:
    • Physics.RaycastAll はすべてのヒット情報を返すため、多数のオブジェクトにヒットする可能性があります。パフォーマンスへの影響を考慮し、必要に応じてレイの最大距離やレイヤーマスクを適切に設定してください。
  • ガベージコレクションの最小化:
    • 頻繁にレイキャストを行う場合、Physics.RaycastNonAlloc を使用することで、ヒット情報を事前に用意した配列に格納し、メモリの割り当てを抑えることができます。
Physics.RaycastNonAlloc のサンプルコード
RaycastHit[] hitResults = new RaycastHit[10]; // 最大10個のヒットを格納
int hitCount = Physics.RaycastNonAlloc(ray, hitResults, 100f, LayerMask.GetMask("Default"));

for (int i = 0; i < hitCount; i++)
{
    Debug.Log("Hit object: " + hitResults[i].collider.name);
}

この方法では、事前に配列を用意しておくことで、ガベージコレクションの発生を防ぎ、パフォーマンスを向上させることができます。ただし、配列のサイズに注意が必要です。ヒット数が配列のサイズを超えると、それ以上のヒットは無視されます。

まとめ

  • 複数のヒットを検出するにはPhysics.RaycastAll または Physics.RaycastNonAlloc を使用します。
  • パフォーマンスを考慮する場合Physics.RaycastNonAlloc を検討し、必要に応じてレイの範囲やレイヤーマスクを調整します。
  • ヒット情報を処理する際RaycastHit の配列をループで回して各オブジェクトに対する処理を行います。

これらの方法を活用することで、複数のオブジェクトに対するレイキャストの検出を効率的に行うことができます。

衝突情報の取得

Raycastがオブジェクトに当たった場合、そのオブジェクトに関するさまざまな情報を取得できます。例えば、オブジェクトの名前や位置などです。

if (Physics.Raycast(ray, out hit))
{
    Debug.Log("Hit object: " + hit.collider.name);
    Debug.Log("Hit point: " + hit.point);
    Debug.Log("Distance: " + hit.distance);
}
  • hit.collider.name: 衝突したオブジェクトの名前を取得します。
  • hit.point: レイが衝突した位置を取得します。
  • hit.distance: レイの発射位置から衝突した点までの距離を取得します。

応用編:距離の指定とレイヤーのフィルタリング

Raycastの応用として、レイの飛距離を指定したり、特定のレイヤーだけを検出することも可能です。

距離を指定する

float maxDistance = 10.0f;
if (Physics.Raycast(ray, out hit, maxDistance))
{
    Debug.Log("Hit within 10 units: " + hit.collider.name);
}

上記の例では、レイを最大で10ユニットの距離まで飛ばし、その範囲内にあるオブジェクトのみを検出します。

レイヤーのフィルタリング

特定のレイヤーのみを検出するには、レイヤーマスクを使います。

int layerMask = LayerMask.GetMask("Enemy");
if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
{
    Debug.Log("Hit enemy: " + hit.collider.name);
}
  • LayerMask.GetMask("Enemy"): レイヤー「Enemy」のみを検出するためのレイヤーマスクを作成します。
  • Mathf.Infinity: 距離を無限に設定して、全ての距離に対してレイを飛ばします。

まとめ

Raycastは、ゲーム内でオブジェクトを検出する非常に便利な手段です。レイの方向や距離、特定のレイヤーを設定することで、プレイヤーの前方に障害物があるかどうかの確認や、射撃のターゲット検出など、さまざまなシーンで活用できます。このチュートリアルを参考に、実際のゲームでRaycastを活用してみてください。

Unity,当たり判定

Posted by hidepon