クリック(スマホではタップ)したゲームオブジェクトを判定する方法

3Dオブジェクトをクリックした時、そのオブジェクトの参照を取得する方法について説明します
これは、FPS(First Person Shooting:一人称シューティングゲーム)で、Aimで照準を合わせ、弾を発射して当たり判定をする場合などに利用できます

Unityチュートリアル

チュートリアルを通して、検証してみましょう

新しくプロジェクトを作成します。

3DでプロジェクトTargetCheckを作成します。

シーンをGameSceneとして、保存します。

標準では、SampleSceneとなっていますので、変更して保存しておきます

Cubeオブジェクトを2つ作成します。

名前をCube1Cube2にします。また、Positionをそれぞれ(0, 0, 0)と(3, 0, 0)としておきます。

GameControllerスクリプトを作成します。

Input.GetMouseButtonDown(0)

は、マウスボタンの状態(ボタンが押された瞬間)を取得するInputクラスのメソッドになります。
0は、左ボタン、1が右ボタン、2が中ボタンの状態を取得できます
もし、ボタンが押されたら、このメソッドはtrueを返すので、if文が成り立つことになります。

マウスの左ボタンをクリックされた時に、コードが実行されるように Update()メソッドに次のようにコードを記述します。

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
    }
}
Input.mousePosition

は、マウスカーソルの座標(スクリーン座標)を取得するプロパティになります。

Ray ray = Camera.main.ScreenPointToRay(引数);

これは、MainCameraタグがついているカメラから、3Dオブジェクトまでの延長線(Ray)をオブジェクトとして取得するメソッドになります。引数は、スクリーン座標になります。

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

今回は、マウスでクリックしたスクリーン座標を引数に取りますので、上記のようになります。

bool success = Physics.Raycast(ray, out RaycastHit hit)

この取得されたrayオブジェクトが、3Dオブジェクトに衝突(Colliderに)した場合、そのオブジェクトの情報を取得するメソッドが用意されています。このRaycast()メソッドは多くのオーバーロードを持っていますが、今回は、2つの引数を持つものを選択します。第1引数には、rayを指定し、第2引数には、衝突してオブジェクトの情報が代入される変数を指定します。out修飾子がついていますが、これとよく似た使い方として、次のようなのがあります。
これは、文字列の123をint型に変換するコードですが、戻り値として、成功したかどうかをsuccess変数に、また成功したときに結果をresult変数に代入するコードになります。

bool success = int.TryParse("123",out int result)

Raycastメソッドも同様にオブジェクトがヒットすると、hit変数にそのオブジェクトの情報が代入されます。また、取得に成功したかどうかは、success変数に代入されます。

hit変数からは、様々な情報を得ることができますが、今回は次のような情報を取得します。

Debug.Log("名前: " + hit.transform.name);
Debug.Log("位置: " + hit.transform.position);
Debug.Log("距離: " + hit.distance);

ここまでをまとめると、

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out RaycastHit hit))
        {
            Debug.Log("光線が当たったオブジェクトの情報");
            Debug.Log("名前: " + hit.transform.name);
            Debug.Log("位置: " + hit.transform.position);
            Debug.Log("距離: " + hit.distance);
        }
    }
}

となります。Unityエディタで、空のオブジェクトを作成し、このスクリプトをアタッチして実行してみましょう。
それぞれのCubeオブジェクトのクリックで、情報が取得できると思います。

hit.transform.GetComponent<MeshRenderer>().material.color = Color.green;

// イメージとしては、次のようになります。TransformコンポーネントをListに持つオブジェクトのコンポーネント取得
// hit.transform.gameObject.GetComponent<MeshRenderer>().material.color = Color.green;

このコードは、ヒットしたオブジェクトを描画するコンポーネント(MeshRenderer)のカラー情報を変更するものになります。
このコードを追加することで、Cubeをクリックするとそのオブジェクトの色が変更される様子が見られると思います。

全コード

最終的に全体コードは次のようになります。

using UnityEngine;

public class GameManeger : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out RaycastHit hit))
            {
                Debug.Log("光線が当たったオブジェクトの情報");
                Debug.Log("名前: " + hit.transform.name);
                Debug.Log("位置: " + hit.transform.position);
                Debug.Log("距離: " + hit.distance);
                hit.transform.GetComponent<MeshRenderer>().material.color = Color.green;
            }
        }
    }
}

Unity

Posted by hidepon