クリック(スマホではタップ)したゲームオブジェクトを判定する方法
3Dオブジェクトをクリックした時、そのオブジェクトの参照を取得する方法について説明します
これは、FPS(First Person Shooting:一人称シューティングゲーム)で、Aimで照準を合わせ、弾を発射して当たり判定をする場合などに利用できます
チュートリアルを通して、検証してみましょう
サンプルプロジェクト
プロジェクトの作成
3Dアプリケーションを選択してTargetCheckという名前で作成します。
シーンをGameSceneとして、保存します。
標準では、SampleSceneとなっていますので、変更して保存しておきます
Cubeオブジェクトを2つ作成します。
名前をCube1とCube2にします。また、Positionをそれぞれ(0, 0, 0)と(3, 0, 0)としておきます。
GameControllerスクリプトを作成します。
スクリプト名GameManegerで作成します
3Dオブジェクトをマウスで左クリックすると、そのオブジェクトの情報が取得できます
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);
}
}
}
マウスの状態取得
マウスボタンの状態(ボタンが押された瞬間)を取得するInputクラスのメソッドになります。
引数が0の場合は左ボタン、1が右ボタン、2が中ボタンの状態を取得できます
もし、ボタンが押されたら、このメソッドはtrueを返すので、if文が成り立つことになります。
Input.GetMouseButtonDown(0)
常にマウスの左ボタンをクリックされたかをチェックし、クリックされると処理が実行されるようにします。
void Update()
{
if (Input.GetMouseButtonDown(0))
{
// 処理
}
}
座標について
スクリーン座標は、PCでは画面、スマホではパネルに当たります
左上が(0, 0)になります
また、別に3Dオブジェクトはx, y, zのワールド座標を持っています
スクリーン座標の取得
マウスカーソルの座標(スクリーン座標)を取得するプロパティになります
Input.mousePosition
Ray(光線)のオブジェクトを取得
MainCameraタグがついているカメラオブジェクトから、3Dオブジェクトまでの延長線(Ray)をオブジェクトとして取得するメソッドになります。引数は、スクリーン座標になります。
Ray ray = Camera.main.ScreenPointToRay(スクリーン座標);
今回は、マウスでクリックしたスクリーン座標を引数にします
マウスポイントの延長線にある3Dオブジェクトまでの光線になります
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Rayからの情報を取得
rayオブジェクトが、3Dオブジェクトに衝突(Colliderに)した場合、そのオブジェクトの情報を取得するメソッドが用意されています。このRaycast()メソッドは多くのオーバーロードを持っていますが、今回は、2つの引数を持つものを選択します。第1引数には、rayを指定し、第2引数には、衝突してオブジェクトの情報が代入される変数を指定します。
bool success = Physics.Raycast(ray, out RaycastHit hit)
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);
スクリプトのアタッチ
Unityエディタで、空のオブジェクトを作成し、このスクリプトをアタッチして実行してみましょう。
それぞれのCubeオブジェクトのクリックで、情報が取得できると思います。
クリックしたオブジェクトの色を変えてみる
ヒットしたオブジェクトにアタッチされているMeshRendererコンポーネント(描画するコンポーネント)のカラー情報を変更してみましょう
Cubeをクリックするとそのオブジェクトの色が変更されるはずです
hit.transform.GetComponent<MeshRenderer>().material.color = Color.green;
// 次でもいいです。transform.gameObjectでオブジェクト取得できます
// hit.transform.gameObject.GetComponent<MeshRenderer>().material.color = Color.green;
全コード
最終的に全体コードは次のようになります。
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;
}
}
}
}
参考
カメラからのRay
Raycast構造体から得られるさまざまな情報
articulationBody | ヒットしたコライダの ArticulationBody。コライダがアーティキュレーション ボディに接続されていない場合は、NULLになります。 |
barycentricCoordinate | ヒットした三角形の重心座標 |
collider | ヒットしたコライダー |
colliderInstanceID | ヒットしたColliderのインスタンスID |
distance | レイの原点から衝突点までの距離 |
lightmapCoord | 衝突点の UV ライトマップ座標 |
normal | レイがヒットしたサーフェスの法線 |
point | レイがコライダーにヒットした位置 (ワールド空間)。 |
rigidbody | ヒットしたコライダーの Rigidbody。コライダーに Rigidbody がアタッチされていない場合は null になります。 |
textureCoord | コリジョン位置の uv テクスチャ座標 |
textureCoord2 | 衝突したセカンダリ UV テクスチャの座標 |
transform | 衝突したコライダーまたは Rigidbody の Transform |
triangleIndex | 衝突したメッシュの三角形におけるインデックス |
ディスカッション
コメント一覧
まだ、コメントがありません