【Unity】Raycastで、imageを取得したい!!

Unity

 

こんばんは、ちきなるです。

 

マウスをクリックした場所に、imageがあるかチェックしたい!!

(imageは、UIから追加できるやつです)

 

imageが有ったら、情報を取得して、

imageが無かったら、何もしない。

 

と、言うわけで、

Raycastで、imageを取得しようとしたら・・・。

(2Dゲームの話です)

補足。

Raycast(Physics2D.Raycast)とは、

指定のポイントから、指定の方向へRay(光線)を発射し、Rayが接触したColliderを返す(RaycastHit2D)関数です。

 

指定のポイント(マウスの位置など)にある、オブジェクトを取得するのに、使われます。

 

これを使って、image(GUI)を取得したい!!

と、言う話です。

 

 

Physics2D.RaycastAll

マウスがあるポイントに、Raycastだ!!

Physics2D.RaycastAllで、全て取得)

//マウスのある位置を取得(スクリーン座標)
Vector3 MousePoint = Input.mousePosition;
//スクリーン座標をワールド座標に変換
MousePoint = Camera.main.ScreenToWorldPoit(MousePoint);

//マウスのある位置から、奥(0, 0, 1)に向かってRayを発射(ワールド座標)
RaycastHit2D[] hit2D = Physics2D.RaycastAll(MousePoint , Vector3.forward);

//Rayがhitしたオブジェクトに目的のオブジェクトがあるかチェック
foreach(RaycastHit2D hit in hit2D)
{
    //中身の確認処理 hit.transform.gameObject.tagとかが便利
}

と、やったのですが・・・。

 

imageは、取得できませんでした。

 

ちなみに、

カメラの設定を透視投影(ProjectionをPerspective)に、している場合、z座標にカメラからの距離を入れてあげないと、上手くオブジェクトを取得できません。

画面の視覚情報と一致させたい場合は、対象のオブジェクトのz座標とカメラのz座標の距離を入力する必要があります。ScreenToWorldPoit前に。

対象オブジェクトのz座標が0の時

//マウスのある位置を取得(スクリーン座標)
Vector3 MousePoint = Input.mousePosition;
//対象オブジェクトとカメラの距離を入れる
MousePoint.z = 0 - Camera.main.transform.position.z;
//スクリーン座標をワールド座標に変換
MousePoint = Camera.main.ScreenToWorldPoit(MousePoint);

この後、Raycastをすると、オブジェクトが取れる。はず。

Physics2DRaycastの対象は、Colliderです。

Rayが通過したポイントにあるColliderを取得する関数です。

 

つまり。

Colliderを持たないimageは、取得することが出来ません。

(imageに、無理やりColliderを付けて取得することも出来ますが、

 それなら、imageではなく、Spriteを使った方が良いです)

 

 

EventSystem.current.RaycastAll

どうすれば、imageが、取得できるのか・・・。

 

と、調べたところ、

EventSystem.current.RaycastAll

と言うのが、ありました。

 

これを使うと、

ポイントに存在する、全てのUI(GUI)を取得することが出来ます。

//RaycastAllの引数(PointerEventData)作成
PointerEventData pointData = new PointerEventData(EventSystem.current);

//RaycastAllの結果格納用List
List<RaycastResult> RayResult= new List<RaycastResult>(); 

//PointerEventDataにマウスの位置をセット
pointData.position = Input.mousePosition;
//RayCast(スクリーン座標)
EventSystem.current.RaycastAll(pointData , RayResult);

foreach (RaycastResult result in RayResult)
{
    //中身の確認処理
}

これで、

マウスがあるポイントのUIを全て取得できます。

 

ただし!!

Raycast Targetにチェックが付いているUIだけです。

ちょっとだけ、余談。

ワールド座標とスクリーン座標

 

Physics2D.RaycastAllは、ワールド座標が使われていましたが、

EventSystem.current.RaycastAllは、スクリーン座標が使われています。

要注意。

 

覚え方としては、

ゲーム内に存在するオブジェクトは、ワールド座標

ユーザーに向けて作られたもの(UI)は、スクリーン座標

 

これが、基本です。

(ワールド座標は、オブジェクトが存在するゲーム空間の座標。

 スクリーン座標は、画面の座標。(左下が(0, 0))

(スクリーン座標とワールド座標では、値の大きさが違います(1≠1))

 

Physics2Dは、ゲームオブジェクト(Collider)が対象なので、ワールド座標

EventSystemは、UIが対象なので、スクリーン座標

 

 

まとめ

Raycastで、image(UI)を取得したい時は、

EventSystem.current.RaycastAll

を使う。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class RaycastTest : MonoBehaviour
{
    //RaycastAllの引数
    private PointerEventData pointData;

    private void Start()
    {
        //RaycastAllの引数PointerEvenDataを作成
        pointData = new PointerEventData(EventSystem.current);
    }
    
    private void Update()
    {
		    //RaycastAllの結果格納用のリスト作成
		    List<RaycastResult> RayResult= new List<RaycastResult>();

	      //PointerEvenDataに、マウスの位置をセット
		    pointData.position = Input.mousePosition; 
		    //RayCast(スクリーン座標)
		    EventSystem.current.RaycastAll(pointData , RayResult);

		    foreach (RaycastResult result in RayResult)
		    {
		        //中身の確認処理
		    }
    }
}

Raycast Targetが付いている全てのUIを取得します。

 TextPanelなども取得できます)

余談2。

 

EventSystemsで送られてきたPointerEventDataの場合、

pointerPressRaycast

を参照するとUIが取得できます(クリックされた時のUI)。

(マウスイベントOnBeginDragなどの引数で渡されたPointerEventDataの話)

 

マウスがクリックされた時、最前面に有るUIが、セットされているもよう。

(ソートを見る感じ、最前面かな?)

 

なので、

OnBeginDragなどで、UIを取得したい時は、eventData.pointerPressRaycastを見るのが良い。

と、思います。

 

ただし、

最前面だけなので、後ろにあるUIを取りたい時は、

RaycastAllで取得する必要があります。

 

 

次回。

コメント

  1. 匿名 より:

    コピペしたらエラーになりました。

    Camera.main.ScreenToWorldPoint

    Camera.main.ScreenToWorldPoit(Pointのnがない)
    になってました。

タイトルとURLをコピーしました