【Unity】FPS系ゲーム制作に使えるraycastの使い方(3D・2D)


「FPSなどのシューティングゲームで、照準はどのようにプログラムしてるんだろう」と思ったことはありませんか?

私自身Unityをしばらく触って動かしているうちに、上記のことが気になったことがあります。

その時、調べて出てきたのがraycastという機能でした。

そこで本記事では、シューティングゲーム以外にも使われている”raycast”という機能に焦点を絞って、

  • raycastとはどういうものか
  • raycastの使い方
  • 簡易的なシチュエーションにおいてのraycastの実装

の順でご紹介いたします。

5分くらいで読めますので、ゲームを作る第一歩となるかと思いますので、ぜひご一読を!

raycastとは

raycastの”ray”とは、光線を意味する単語になります。

unityではある特定のオブジェクトから透明な光線を出し、光線がぶつかった別のオブジェクトの座標を取得する機能をraycastと呼んでいます。

座標に関しては詳細こちら→)【Unity】同次座標系をマスターしよう -「w」の正体まで徹底図解!

用途としては、FPSにおける照準やアイテム取得における注視などに使われることが多いです。

便利な機能ではありますが、発生させる光線の数を増やしすぎたり、必要以上に長くしすぎたりすると下記のようなデメリットも生じるので注意が必要です。

  • ゲーム自体の動作が重くなる
  • 多くのオブジェクトに対するテストが必要になる

raycastを使ってみよう

オブジェクトに設定するColliderに3D、2Dがあるように、raycastにも3D、2Dがあります。

Colliderに関する記事はこちら→【Unity】Colliderによる当たり判定を理解しよう!

関数に受け渡す値と返り値に若干の違いがありますのでそれぞれ解説します。

今回使用した環境の情報は下記になります。

  • モデル:MacBook(Ratina,12inch,2017)
  • OS:macOS Mojave 10.14.3
  • CPU:Intel Core i7
  • GPU:Intel HD Graphics  615
  • Unityのバージョン:Unity 2019.1.3f1

3Dにおけるraycastの使い方

Rayの飛ばし方

raycastにおいて、Rayを飛ばすときの引数の取り方は複数用意されていますが、代表的なパターンとしては下記の2パターンがあります。

1つ目は、Rayの発射位置と方向を指定するパターン

2つ目は、直接Rayクラスを持った変数を設定するパターン

Physics.Raycastに与えている引数に違いがみられるのがわかるかと思います。

マウスポインタのある位置のオブジェクト情報の取得

一見は百聞に如かずということで、raycastを使用してオブジェクト上にマウスポインタを置くと

オブジェクト情報を取得するものを実装してみます。

まずは、検知するオブジェクトを配置します。

Plane,Cube,Sphereを下記のように配置し、それぞれのColliderを設定します。

初期配置

次にスクリプトファイルを作成し、下記のスクリプトを入力します。

空のオブジェクトを生成し、先ほどのスクリプトファイルをアタッチし、実際に動作させると

下記のようにマウスポインタが載っているオブジェクトの情報がコンソール画面に出力されます。

実行結果その1

レイヤーと取得範囲の制限

先ほどのスクリプトでは、Rayによる検出から特定のオブジェクトを外すことができません。

そこで必要となってくるのが、レイヤーとレイヤーマスクになります。

インスペクターウィンドウにある下記の画像の部分でレイヤーは設定していきます。

インスペクターウィンドウ【レイヤー】

単純な除外であればレイヤードロップダウンメニューからIgnore Raycastを選択すれば簡単に設定はできます。

しかし、Ignore Raycastは簡単に設定できる反面、色々な変更に対応できなくなります。

そこでレイヤーマスクを利用し、色々な変更に対応できる検出を設定していきます。

まず、画面上にある検出の対象とするCubeとSphereオブジェクトを、それぞれレイヤーを分けてみます。

インスペクターウィンドウのLayer→Add Layerを選択し、User Layer 8、9にそれぞれcube/sphereを定義します。

レイヤーの追加

定義後、それぞれのオブジェクトのレイヤードロップダウンメニューから対応したものを選択しておきます。

先ほどのスクリプトをCubeとSphereのみを検出するように修正します。

実際に動作させてみると下記のようになります。

実行結果その2

最初のスクリプトと違いPlaneオブジェクトを検出せずに、CubeとSphereオブジェクトのみを検出しているのがわかると思います。

重なった複数のオブジェクトの検出方法

次に重なった複数のオブジェクトはどうでしょうか。

下記のようにCubeオブジェクトを設置してみます。

重なりのある配置

先ほどのスクリプトでも重なったオブジェクトは検出をしないので別の方法を取る必要があります。

そこで利用するのが、Rayの当たった全てのオブジェクトを検出するPhysics.RaycastAllになります。

スクリプトは下記のようになります。

実際に動作させてみると下記のようになります。

実行結果その3

Physics.RaycastAllにより、Cubeオブジェクトに重なっているCube2の名前が検出されているのがわかります。

raycastを可視化してみる

デバッグ時にちゃんとRayが想定したように出ているか確認したいこともあるかと思います。

その時に使用するのがDrawRayになります。

CubeとSphereのみを検出するスクリプトに追記をします。

実行してみると下記のようになります。

実行結果その4

Sceneビューをみるとスクリプトで指定した通り緑の線が出ていることがわかります。

2Dにおけるraycast

マウスポインタのある位置のオブジェクト情報の取得

それでは2Dにおけるraycastもみていきましょう。

2DではPhysics2D.Raycastを使用します。

初期配置として今回は、アセットストアから「Simple Avatar icon」を使用します。

Simple Avatar Icon

 

初期配置

スクリプトは下記になります。

 

実行結果は下記のようになります。

実行結果その5

3Dのときと同様に検出が行われていることがわかります。

2Dと3Dとの違いは下記になります。

  • Rayを開始位置と方向のベクトルの代わりに引数として設定できない
  • 返り値が3Dではbool値だが、2DではRaycastHit2Dが返り値となっている
  • Rayの開始位置のオブジェクトも検出の対象となる

raycastを可視化してみる

2DにおいてもRayの可視化は可能です。

3Dの時のようにカメラからRayを飛ばしても2Dでは見えないのでElf_2のアイコンからElf_1のアイコンに向かってRayを飛ばしてみます。

実際に動作させてみると下記のようになります。

実行結果その6

Elf_2から出ているRayからElf_1をずらすと検出されていないのがわかると思います。

raycastを使用したゲームの実装

今回はraycastを使用して簡易的な的当てゲームを実装してみます。

アセットとして「Military target」をアセットストアからインストールします。

アセット【Military target】

まずは、Plane,SphereオブジェクトとMilitary targetを下記のように配置します。

配置

新規レイヤーとしてtargetを8番目に作成し、targetのオブジェクトに適用します。

targetレイヤー

飛ばすボールとしてのSphereオブジェクトに、RigidbodyとSphere Colliderを設定します。

Rigidbodyについてはこちら→)【Unity】Rigidbodyを使用して重力・空気抵抗を発生させる方法

各種設定が済んだらSphereオブジェクトに対し、ボールの挙動を設定するスクリプトを適用します。

 

このスクリプトでは、ボールに対し飛ばすための力を与えることと的に衝突したらそのまま的に張り付くという動作を記述しています。

スクリプトができたら適用したSphereオブジェクトをヒエラルキーウィンドウからプロジェクトウィンドウにドラッグ&ドロップしてPrefabにします。

Prefabの使い方はこちら→)【Unity】 Prefabを使ったオブジェクト生成・複製・削除等の方法

このPrefabを利用して同じ挙動をするボールを複製するスクリプトを記述していきます。

上記が飛んでいくSphereオブジェクトを生成するスクリプトになります。

Rayを使用して画面上でクリックした方向へSphereオブジェクトが飛ぶように設定しています。

また、デバッグ用に的に当たっているかの情報を取得するためにraycastを利用しています。

スクリプトが書けたら空のゲームオブジェクトを作りアタッチします。

実際に動作をさせると下記のようになります。

実行結果その7

ボールが飛んでいく方向に的があった場合、コンソールに情報が取得できているのがわかると思います。

まとめ

いかがでしたでしょうか。

今回はraycastについて解説していきました。

FPSや脱出ゲームなどを作成する時などには必要な要素になりますので、実際に色々試しながら実装をしてみてください。

この記事が、Unityを学んでいる人の参考になれば幸いです!

合わせて読みたい関連記事)


Yuhei Fujie