【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の個別指導のオンラインレッスンを行っています。
ご興味のある方は当サイト、オンラインレッスンから、無料体験授業へお問い合わせ下さい。
いいなと思ったら応援しよう!
よろしければ応援お願いします! いただいたチップはクリエイターとしての活動費に使わせていただきます!