ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Unity - Raycaster:Ray を飛ばしてクリックやドラッグをしたオブジェクトを検出し、イベントを発生させる -

初めに

 Raycaster とは、Ray(光線)をcast(投射)したとき、Ray になにかがぶつかったことを検出する仕組みです。例えば、クリックした場所から Ray を飛ばすことで、クリックした場所にあるオブジェクトを取得することができます。この記事では、Raycaster についてまとめます。

Raycaster

Ray とは

 Raycaster を扱うとき Ray が必要になります。Ray について知りたい方は以前、記事にまとめたのでそちらからご覧ください。

fineworks-fine.hatenablog.com

Raycaster とは

 Raycaster とは、EventSystem で用いられる Ray(光線)をcast(投射)したとき、Ray になにかがぶつかったことを検出することができる仕組みです。
 使用するには EventSystem が必要になります。
fineworks-fine.hatenablog.com

Raycaster の種類

 Raycaster には次の種類があります。

Raycaster 説明
Graphic Raycaster UI 要素で使用し、キャンバス上で有効で、キャンバス内を検索します
Physics Raycaster 3D 物理要素で使用します
Physics 2D Raycaster 2D 物理要素で使用します

docs.unity3d.com

Graphic Raycaster

Graphic Raycaster とは

 Graphic Raycaster は UI 要素に対して使用します。Canvas オブジェクトにGraphic Raycaster コンポーネントをつけて使用します。(Canvas を生成するとはじめからついています。)

 Canvas オブジェクトへの Raycast(レイキャスト)に用いられます。Graphic Raycaster は Canvas 上にあるボタン等のUIを監視し、どれにタッチされたかを判定しています。

機能 説明
Ignore Reversed Graphics false だとRaycaster のほうを向いていないオブジェクトの判定が取れる
Blocked Objects レイキャストをブロックするオブジェクトを選択する
(None : なし、Two D : 2D、Three D : 3D、All : すべて)
Blocking Mask レイキャストをブロックするオブジェクトがあるレイヤーを選択する

fineworks-fine.hatenablog.com

Raycast Target

 各 UI 要素のコンポーネントにある Raycast Target が true であれば、Ray がぶつかったことを検出できます

Physics Raycaster

Phisics Raycaster とは

 3Dオブジェクトに対して使用します。Camera オブジェクトに追加して使用します。

機能 説明
Event Mask Raycast target にする Layer を選択できる
Max Ray Intersections Ray の交わりが検出できる最大数

docs.unity3d.com
docs.unity3d.com

Physics.Raycast

 Physics.Raycast を使うことで Ray を投射し、ぶつかったオブジェクトの情報を取得することができます。

public static bool Raycast (Vector3 origin, Vector3 direction, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);

引数 説明
origin ワールド座標でのレイの開始地点
direction レイの方向を表すベクトル
maxDistance レイが衝突を検知する最大距離
layerMask レイヤーマスクはレイキャストするときに選択的に衝突を無視するために使用します
queryTriggerInteraction トリガーに設定されているものも検索対象にするか

(注意点)

  • origin と directionで指定した Ray の始点と方向は、Ray そのものを引数にすることも可能です。
  • Physics.Raycast は bool 関数のため、返り値は true/false です。Ray がぶつかったオブジェクトの情報は RaycastHit で取得します。(詳細は下記の使用例で説明)

(使用例の1つ)
クリックしたオブジェクトの名前をログに表示させる

private void Update () {
	
  //メインカメラ上のマウスカーソルのある位置からRayを飛ばす
  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  RaycastHit hit;

  if (Physics.Raycast(ray, out hit)){
    //Rayが当たるオブジェクトがあった場合はそのオブジェクト名をログに表示
    Debug.Log(hit.collider.gameObject.name);
  }  
}

 Ray がオブジェクトにぶつかったら Physics.Raycast が true になり、if文の中に入ります。その際、Ray を発射するときに参照を渡した RaycastHit の hit に衝突したオブジェクトの情報が入っています。RaycastHit で読み取れる情報は下のドキュメントをご覧ください。
docs.unity3d.com

 Physics.Raycast のドキュメントに他の使用例がいくつか紹介されています。
docs.unity3d.com

Eventの設定の仕方

 次の手順で3Dオブジェクトに Event を追加できます。

  • カメラオブジェクトにAdd Component>Event>Physics Raycaster を追加
  • 3DオブジェクトにAdd Component>Event>Event Triggerを追加
  • 3DオブジェクトにCollider がついていなければ追加
  • Event TriggerのAdd New Event Typeで Event Type を追加し、Event を追加する
  • Hierarchy にEventSystem を追加

 Physics Raycaster で Ray を管理し、Event System でユーザーからの入力を管理しています。それらが Ray が3Dオブジェクトの Collider にぶつかったことを検出し、Event Trigger で設定した関数を呼び出すという仕組みです。

 Event Type では、イベント発生のタイミングが指定できます。Event Type は次の種類があります。



EventType 説明
Pointer-- ポインターが条件を満たしたとき
Enter:オブジェクトに乗ったとき
Exit:オブジェクトから離れたとき
Down:オブジェクトを押下したとき
Up:押下状態からはなしたとき
Check:オブジェクト上で押下し、同一のオブジェクト上で離したとき
Drag オブジェクトがドラッグされている間
Drop ドラッグされてきた他のオブジェクトが、範囲内でドラッグ解除されたとき
Scroll オブジェクトの範囲内でマウスホイールをスクロールしたとき
UpdateSelected 選択中のオブジェクトで毎フレーム発生
Select オブジェクトが選択されたとき
Deselect オブジェクトの選択状態が解除されたとき
Move 選択状態で方向キーの入力があったとき
InitializePotentialDrag ドラッグ対象をクリックしたとき
BeingDrag ドラッグを開始したとき
EndDrag ドラッグが終了したとき
Submit サブミットボタンが押されたとき
submit は提出を意味する。デフォルトはリターンキー(Enter)
Cancel キャンセルボタンが押されたとき
デフォルトはエスケープキー

docs.unity3d.com

 Event Type 選択後は、Button と同じように、呼び出される関数を指定してイベントを設定できます。

Physics 2D Raycaster

Physics 2D Raycaster とは

 Sprite など2Dオブジェクトに対して使用します。Camera オブジェクトに追加して使用します。

docs.unity3d.com

Physics Paycaster(3Dの場合)との違い

 基本的な使い方は同じですが、違う部分もあります。細かい違いは下記のようなものがあります。

  • Collider ではなく Collider2Dを使用する必要がある
  • Physics.Raycast ではなく Physics2D.Raycast を使う

Physics2D.Raycast
public static RaycastHit2D Raycast (Vector2 origin, Vector2 direction, float distance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, float minDepth= -Mathf.Infinity, float maxDepth= Mathf.Infinity);

 基本的には、Physics.Raycast と同じです。

 Physics.Raycast と違う部分を紹介します。

  • minDepth と maxDepth が追加
  • origin, direction を Ray で指定できない
  • (最重要)返り値が違う

 minDepth と maxDepth が追加されていますが、これは Ray が衝突する z 座標の範囲を指定できます。(多分、使うことはないと思います。)

 3Dの場合、origin, direction を Ray でも指定できましたが、2Dの場合はできないようです。

 最も大きな違いは返り値が違います。

返り値
Physics.Raycast bool
Physics2D.Raycast RaycastHit2D

 3Dの場合と違い、下のような記述が可能になります。

 RaycastHit2D hit = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction, maxDistance, layerMask);

docs.unity3d.com

最後に

 Raycaster についてまとめました。Raycast を扱うには必要なコンポーネントやオブジェクトが多く分かりづらい部分もあります。しかし、丁寧にやらないとオブジェクトが重なったとき、クリックしたいオブジェクトが反応しないようなことが起きますので、注意しましょう(自戒)。