見出し画像

【Unity初心者向け】Raycast の活用① | Raycastとは? 見えない線で障害物を調べ る

Unityでは、敵が壁を見つけたり、プレイヤーが地面に立っているか調べたり、銃を撃って敵に命中したか判定したりすることがあります。

このように「この方向に何かある?」を調べるときに便利なのが Raycast(レイキャスト) です。

Raycast を使うと、ある場所から指定した方向へ見えない線を飛ばして、その線上に Collider があるか調べることができます。

今回から全5回で、Raycastの基本からゲームでの活用方法まで確認していきます。

第1回では、まず

  • Raycastとは何か

  • Rayを飛ばす開始位置

  • Rayを飛ばす方向

  • Rayを飛ばす距離

  • Physics2D.Raycast()

  • RaycastHit2D

  • Debug.DrawRay()

について確認していきましょう。



Raycastとは?

Raycast は簡単にいうと「指定した方向へ見えない線を飛ばして、その先に何があるか調べる仕組み」です。

たとえば、キャラクターの前方へ Ray を飛ばします。
その先に壁があれば「前に壁がある」と判断できます。
反対に、Ray が何にも当たらなければ「前には何もない」と判断できます。

ゲームでは、この仕組みをさまざまな場面で利用できます。
たとえば、

  • 敵の前に壁があるか調べる

  • キャラクターの足元に地面があるか調べる

  • 敵からプレイヤーが見えているか調べる

  • 銃を撃ったときに何に命中したか調べる

  • マウスでクリックした場所に何があるか調べる

といった使い方があります。


Raycastの基本情報

Raycastを飛ばすには、大きく3つの情報が必要です。
それが、

  • origin

  • direction

  • distance

です。


origin ― どこから飛ばす?

origin は、Rayを飛ばし始める場所です。

たとえば、

transform.position

を指定すると、そのオブジェクトの現在位置からRayを飛ばします。


direction ― どちらへ飛ばす?

direction はRayを飛ばす方向です。

  • 右方向なら → Vector2.right

  • 左方向なら → Vector2.left

  • 上方向なら → Vector2.up

  • 下方向なら → Vector2.down

などを使用できます。


distance ― どこまで調べる?

distance はRayを飛ばす距離です。

たとえば、3f と指定したなら、開始位置から3ユニット先まで調べます。




Colliderのイベント関数とは何が違う?

Unityには、Raycast以外にもColliderを使ってオブジェクトを調べる方法があります。

たとえば、

OnCollisionEnter2D()

や、

OnTriggerEnter2D()

これらを使うと、オブジェクト同士が接触したり、Trigger 範囲に入ったことを確認できます。

では、Collider のイベント関数があるのに、なぜ Raycast を使うのでしょうか。
大きな違いは「接触してから調べるのか、接触する前に調べるのか」という点です。


Colliderは「触れたこと」を調べる

たとえば、敵が右方向へ移動していて、その先に壁があるとします。
敵と壁が実際にぶつかると、

OnCollisionEnter2D()

などのイベント関数を使って「壁にぶつかった」ことを確認できます。
また、ColliderをTriggerにしておけば、

OnTriggerEnter2D()

を使って「指定した範囲に入った」ことを調べることもできます。

このような処理は、

  • プレイヤーが敵に触れた

  • アイテムを取得した

  • ゴールエリアに入った

  • ダメージエリアに入った

といった判定に向いています。


Raycastは「この先に何がある?」を調べる

一方、Raycastではオブジェクトが実際に接触する前に「この方向に何かある?」と調べることができます。

敵と壁はまだ離れているとき、Rayが壁に当たれば「少し先に壁がある」と判断することができます。
つまりRaycastは、オブジェクトに取り付ける「見えないセンサー」のような使い方ができます。


Raycastが便利なのは「何もない場所」も調べられること

Raycastが特に便利なのが、地面や崖を調べる場合です。
たとえばキャラクターが足場の上を歩いているとします。
キャラクターの少し前から下方向へRayを飛ばします。

Rayが地面に当たっていれば「この先にも地面がある」と判断できます。

しかしキャラクターが崖の近くまで進むと、Rayが何にも当たらなくなります。
このとき「この先には地面がない」
つまり「崖がある」と判断できます。

ここがColliderのイベント関数との大きな違いです。
崖の先にはColliderがありません。
そのため「崖にぶつかった」というイベントは発生しません。

Raycastなら、Colliderがあるかだけでなく、Colliderがないことも調べられるため、このような判定に向いています。


ColliderとRaycastの使い分け

どちらか一方だけを使えばよい、というわけではありません。

処理の目的によって使い分けます。

やりたいこと向いている方法プレイヤーが敵に触れたColliderイベントアイテムを取得したTriggerイベントゴールエリアに入ったTriggerイベント敵の前に壁があるか調べるRaycast足元に地面があるか調べるRaycastこの先が崖になっているか調べるRaycast敵からプレイヤーが見えるか調べるRaycast銃を撃って何に当たったか調べるRaycast

覚え方としては、

  • 「触れたことを知りたい」→ Colliderのイベント関数

  • 「この方向に何があるか調べたい」→ Raycast

と考えると分かりやすいでしょう。


Triggerをセンサーにする方法もある

実は、敵の前方にTrigger用のColliderを配置して、

OnTriggerEnter2D()

を使って障害物を検知する方法もあります。
この方法でも簡単なセンサーを作ることはできます。
ただし、

  • 前方向だけ調べたい

  • 下方向だけ調べたい

  • 一定の距離まで調べたい

  • プレイヤーまで一直線に見えているか調べたい

といった場合には、Raycastの方が扱いやすくなります。

Raycastは、開始位置・方向・距離を指定するだけで、必要な場所をピンポイントに調べることができるからです。




Raycastのサンプル

オブジェクトの配置

それでは、実際にRaycastを使ってみます。
今回は2Dで確認します。

HierarchyにRayを飛ばすためのオブジェクトを1つ用意します。
名前は「RayObject」としておきます。
Spriteは四角形など、何でも構いません。

次に、その右側へ障害物となるオブジェクトを配置します。
名前は「Wall」としておきましょう。

Wallには「Box Collider 2D」を追加してください。
RaycastはColliderを調べる仕組みなので、調べたいオブジェクトにColliderが必要です。

今回は物理的に動かすわけではないため、Rigidbody2Dを追加する必要はありません。


スクリプトを作成

Projectウィンドウで、スクリプトファイル:RaycastBasic を作成し、RayObject へアタッチします。

まず、Rayを飛ばす距離を設定する変数を作ります。

public float rayDistance = 3f; // Raycastの距離

今回は3ユニット先まで調べることにします。

Raycastを飛ばすには、

Physics2D.Raycast()

を使います。
まずは次のように書いてみましょう。

void Update()
{
    Vector2 origin = transform.position;   // Raycastの発射位置
    Vector2 direction = Vector2.right;     // Raycastの方向
    // Raycastを実行
    RaycastHit2D hit = Physics2D.Raycast(origin, direction, rayDistance);
}

順番に確認します。


Rayを飛ばす開始位置を作る

まずは origin に RayObject の現在位置を入れています。

Vector2 origin = transform.position;

つまり、RayObject の位置から Ray を飛ばす という意味です。


Rayを飛ばす方向を作る

今回は右方向へ Ray を飛ばしたいので、Vector2.right を使います。

Vector2 direction = Vector2.right;

これで、RayObject の位置から右方向に Ray が飛びます。


Physics2D.Raycast()の中を確認

Physics2D.Raycast(origin, direction, rayDistance);

で実際にRayを飛ばしています。
今回使っている3つの値を当てはめると、

Physics2D.Raycast(
    origin,         // Raycastの発射位置
    direction,      // Raycastの方向
    rayDistance     // Raycastの距離
    );



RaycastHit2Dとは?

先ほどのコードでは、

RaycastHit2D hit =
    Physics2D.Raycast(origin, direction, rayDistance);

と書きました。
ここで登場する、RaycastHit2D とは何でしょうか。

Physics2D.Raycast() はRayを飛ばすだけではありません。
Rayを飛ばした結果、「何に当たったのか」という情報を返してくれます。

その結果を受け取るために使うのが、RaycastHit2D です。
今回は、

RaycastHit2D hit

という変数を作って、その中へRaycastの結果を入れています。

RaycastHit2D の中には、

  • 何に当たったか

  • どの位置に当たったか

  • どの向きの面に当たったか

  • Rayの開始地点からどれくらい離れているか

など、さまざまな情報が入っています。

今回はまず「Raycastの結果を受け取る箱」くらいのイメージで大丈夫です。


Debug.DrawRay()でRayを可視化

ここまででRaycastは実行されています。
しかし、GameビューやSceneビューを見ても、何も表示されません。
これはRaycastが、見えない線だからです。

Raycastはゲーム内部で判定するためのもので、実際に赤いレーザーなどが表示されるわけではありません。

そこで、開発中にRayを確認するときに便利なのが、

Debug.DrawRay()

です。

Update() の中へ次のコードを追加します。

Debug.DrawRay(                  // デバッグ用にRayを可視化
    origin,                     // Raycastの発射位置
    direction * rayDistance,    // Raycastの方向と距離
    Color.red                   // Rayの色    
    );

これでSceneビューに赤い線が表示されます。

ここで少し注意があります。

Physics2D.Raycast() では、direction と、rayDistance を別々に指定しました。
しかし Debug.DrawRay() では、Rayの方向と表示する長さをまとめて指定するため、

direction * rayDistance

としています。
たとえば、

Vector2.right * 3f

なら、右方向へ3ユニット という意味になります。


ここは大切なポイントです。

Physics2D.Raycast()

と、

Debug.DrawRay()

は同じものではありません。

Physics2D.Raycast() は、実際にColliderを調べる処理です。

一方、Debug.DrawRay() は、Rayがどこへ飛んでいるのか人間が確認するための線です。

Debug.DrawRay() を消しても Raycast そのものは動作します。



完成したスクリプト

ここまでのコードをまとめると次のようになります。

public float rayDistance = 3f;

void Update()
{
    Vector2 origin = transform.position;
    Vector2 direction = Vector2.right;

    RaycastHit2D hit =
        Physics2D.Raycast(
            origin,
            direction,
            rayDistance
        );

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

Unityを実行してSceneビューを確認してください。

RayObjectから右方向へ赤い線が表示されれば成功です。


Rayの距離を変更

rayDistance は、

public float rayDistance = 3f;

としているため、Inspectorから変更できます。

RaycastはRayが届いている範囲だけを調べます。
そのため、ゲームを作るときには「どのくらい先まで調べたいのか」を考えて距離を決めることが重要です。



Rayが何かに当たったか確認

最後に、Raycastが実際にColliderを検知できていることだけ確認してみましょう。
先ほど作った、

RaycastHit2D hit

の中にはRaycastの結果が入っています。
そこで、

if (hit.collider != null)
{
    Debug.Log("何かに当たっています");
}

を追加します。
体は次のようになります。

public float rayDistance = 3f;  // Raycastの距離   

void Update()
{
    Vector2 origin = transform.position;   // Raycastの発射位置
    Vector2 direction = Vector2.right;     // Raycastの方向
    // Raycastを実行
    RaycastHit2D hit = Physics2D.Raycast(
        origin,         // Raycastの発射位置
        direction,      // Raycastの方向
        rayDistance     // Raycastの距離
        );

    
    Debug.DrawRay(                  // デバッグ用にRayを可視化
        origin,                     // Raycastの発射位置
        direction * rayDistance,    // Raycastの方向と距離
        Color.red                   // Rayの色    
        );

    if (hit.collider != null)   // Raycastが何かに当たった場合
    {
        Debug.Log("何かに当たっています");
    }
}

WallをRayの範囲内へ移動すると、

何かに当たっています

とConsoleへ表示されます。
WallをRayの届かない場所へ移動すると表示されなくなります。

ここでは、

hit.collider

についてには次回、詳しく確認します。

今は、RayがColliderに当たったか確認できるということだけ分かればOKです。



2Dと3Dでは使うRaycastが違う

今回は2Dゲームなので、Physics2D.Raycast() を使っています。

3Dゲームでは、Physics.Raycast() を使用します。

今回のシリーズでは、初心者にも動作を確認しやすいように、Physics2D.Raycast() を使って進めていきます。

基本的なRaycastの考え方は2Dでも3Dでも同じです。


今回のまとめ

今回は、Raycastの基本的な仕組みを確認しました。


次回はRaycastで地面や壁を判定しよう

今回はRaycastを飛ばして「何かに当たっている」ところまで確認しました。
しかし実際のゲームでは、「何に当たったの?」を調べる必要があります。

次回は、hit.collider を使ってRayが当たったオブジェクトを調べます。

さらに LayerMask を使って、
「地面だけを調べる」
「壁だけを調べる」
といった判定にも挑戦します。

Raycastが少しずつ、ゲームで使えるセンサーになっていきます。


こちらはUnity初心者向けの記事をテーマ別にまとめています。
▼ Unity初心者向け記事まとめはこちら


こちらのマガジン「ミニゲーム作成講座 全8回セット」でもシーンの切り替えなどを活用して、初心者でも知識ゼロから作れるミニゲーム作成講座を紹介しています。

さらにステップアップの「スマホで遊ぶジャンプゲーム 8回セット」のマガジンもぜひご活用ください。


ファイブボックスでは、スクラッチやUnityの個別指導のオンラインレッスンを行っています。
ご興味のある方は当サイト、オンラインレッスンから、無料体験授業へお問い合わせ下さい。

いいなと思ったら応援しよう!

ファイブボックス よろしければ応援お願いします! いただいたチップはクリエイターとしての活動費に使わせていただきます!