LessonEX EventTrigger
EX-1 ボタンの説明を表示
Buttonコンポーネントを使えばボタンへのクリック検知はできますが、それだけでは自由度が足りない時もあります。EventTriggerを使ってマウスオーバー(オブジェクトにマウスが重なっている状態)を検知してみましょう。
まずはUIから適当なButtonとボタンの説明用のText(またはTextMeshPro)を追加してください。説明文の内容は適当で構いません。

ButtonにAdd Componentから「Event Trigger」を追加してください。

新しいスクリプトTestButtonを作成して、以下のように入力してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestButton : MonoBehaviour
{
// ボタンの説明文
public GameObject TestMessageObject;
// マウスが重なった瞬間に呼ばれる
public void TestEnter()
{
// ボタンの説明文を表示する
TestMessageObject.SetActive(true);
}
// マウスが離れた瞬間に呼ばれる
public void TestExit()
{
// ボタンの説明文を非表示にする
TestMessageObject.SetActive(false);
}
// ボタンが押された瞬間に呼ばれる
public void TestPush()
{
// ボタンが押された
Debug.Log("ボタンが押された!");
}
}
ボタンにマウスが重なった時、離れた時、クリックされた時の3つの関数を用意しています。どの関数も外部から呼べるようにpublicにしてください。
スクリプトが書けたらボタンにアタッチしておきましょう。
インスペクターにマウスオーバー時に表示するオブジェクトを指定する項目が表示されるので、先ほど作成したTextオブジェクトをドラッグ&ドロップしてください。

EventTriggerの「Add New Event Type」をクリックすると、関数が呼ばれる条件を選択することができます。
様々な項目がありますが、よく使うと思われるのは以下の項目です。
PointerEnter :マウスカーソルが重なった瞬間
PointerExit :マウスカーソルが離れた瞬間
PointerDown :自身がクリックされた瞬間
PointerUp :自身がクリックされた状態から離れた瞬間
PointerClick :自身がクリックされて同一オブジェクト上で離された瞬間
Drag :オブジェクト上でマウスが押されたまま移動している間
Drop :ドラッグされた他のオブジェクトが自身の上でドラッグ解除された時
Scroll :自身の上でマウスホイールが操作された時
EventTriggerは選択した条件で好きな関数を呼ぶことができます。まずはPointerEnterを選択しましょう。

PointerEnterでは「自身にマウスカーソルが重なった時」に実行する関数を指定できます。新しい項目を追加して、先ほど作成したTestEnter関数を設定してください。



同じようにPointerExitも設定します。呼び出す関数はTestExitにしておきましょう。

Buttonコンポーネントではボタンが押された時に呼ばれる関数を設定できます。
ここではTestPush関数を呼ぶように設定してください。操作の流れはEventTriggerと変わりません。

最初から説明文が見えては困るので、説明文のオブジェクトを非アクティブにしておいてください。

ここまでできたら実行して、マウスカーソルが重なっている間だけ説明文が表示され、クリックするとコンソールにログが出力されることを確認してみてください。

実行する関数に引数を設定することで、インスペクターから引数を指定することもできます。
TestButtonスクリプトを赤い部分のコードに変更してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestButton : MonoBehaviour
{
// ボタンの説明文
//public GameObject TestMessageObject;
// マウスが重なった瞬間に呼ばれる
public void TestEnter(GameObject TestMessageObject)
{
// ボタンの説明文を表示する
TestMessageObject.SetActive(true);
}
// マウスが離れた瞬間に呼ばれる
public void TestExit(GameObject TestMessageObject)
{
// ボタンの説明文を非表示にする
TestMessageObject.SetActive(false);
}
// ボタンが押された瞬間に呼ばれる
public void TestPush()
{
// ボタンが押された
Debug.Log("ボタンが押された!");
}
}
この変更を行うと、関数を変更したことでボタンのEventTriggerの参照が外れます。もう一度設定してください。

再設定すると先ほどとは異なり引数を設定する枠が表示されます。それぞれに説明文のオブジェクトをドラッグ&ドロップ してください。

設定できたら実行して、先ほどと同じ挙動をすることを確認してみてください。
コンポーネントに変数を持たせるか引数を使うかは状況に応じて使い分けましょう。
EX-2 Spriteの判定
UIであれば上記の方法でマウスオーバーを判定できますが、ModelやSpriteの場合は少し手順を挟みます。
まずは適当なSpriteを追加してください。プロジェクト内のスプライトをシーンにドラッグ&ドロップすると、自動でスプライトオブジェクトが作成されます。

UIと異なる点として、対象にコライダーがアタッチされていないと動作しないという点があります。
SpriteにColliderを設定してください。Spriteにアタッチするものは2DがついているColliderでないと正常に動作しないので注意しましょう。
(サンプルではCircle Collider 2Dをアタッチしています。BoxやCapsuleでも構いません)

Main CameraにPhysics 2D Raycasterを追加してください(3Dオブジェクトを検知したい場合はPhysics Raycasterをアタッチ)
Raycasterのパラメータは特に変更する必要はありません。

次はEventSystemを追加してください。
通常、UIを作成した際に自動で追加されるものです。すでにEventSystemが存在する場合は追加しなくて構いません。

後はボタンと同じようにEventTriggerとスクリプトをアタッチして設定するだけです。3Dモデルも同じようにマウスオーバー判定を取ることができるので、覚えておきましょう。
EX-3 マウスで移動させる
ここからは使用例として、EventTriggerを使ったオブジェクトをドラッグ&ドロップで移動させる処理を実装してみましょう。
EX-2の設定を行った状態で、以下のコードを入力してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestButton : MonoBehaviour
{
// ドラッグ中に呼ばれる関数
public void DragTest()
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0.0f; // Z座標を調整する
transform.position = mousePos;
}
}
EventTriggerをリセットして、ドラッグ中にDragTestが実行されるように設定しましょう。


これでスプライトをドラッグで移動させられるようになりました。実行して確認してみてください。
この移動方法は移動中に障害物があってもそのまま貫通してしまいます。次は当たり判定を持ったまま移動させてみましょう。
まずはAdd ComponentからスプライトにRigidBody2Dを追加してください。
後で移動させる時に備えてRigidBody2Dのパラメータを設定しておきます。
LinearDrag は移動の減衰率です。オブジェクト同士がぶつかった際に大きく飛ばないように大きな値にしています(もっと大きい値でもOK)
GravityScale は重力の大きさです。LinearDragを大きくすると重力の影響まで小さくなってしまうので、大きな値にしています。
Collision Detection は移動の計算方式を設定できます。初期値はDiscreteですが、Continuousに変更することで少し正確な判定を取ることができます。ただしDiscreteより処理が重いので扱いには注意が必要です。

このままでは重力でスプライトが落下してしまうので、地面を作成しましょう。インスペクターから「2D Object」→「Sprites」→「Square」を選択してください。
2Dは最初からコライダーがついていないので、コライダーも追加しましょう。

スクリプトは以下のように変更します。移動開始時、移動終了時、Updateの3つの関数を用意しています。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestButton : MonoBehaviour
{
public Rigidbody2D RB2D;
bool IsMove = false;
// 移動開始
public void MoveStart()
{
IsMove = true;
RB2D.gravityScale = 0.0f; // 移動中は重力を無視する
RB2D.freezeRotation = true; // 移動中は回転しないようにする
}
// 移動終了
public void MoveEnd()
{
IsMove = false;
RB2D.gravityScale = 10.0f;
RB2D.freezeRotation = false;
RB2D.velocity = Vector2.zero; // 移動速度をリセットする
RB2D.angularVelocity = 0.0f; // 回転速度をリセットする
}
private void Update()
{
// 移動中なら移動処理
if (IsMove)
{
Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
pos.z = 0.0f;
RB2D.MovePosition(pos);
}
}
}
【プログラムの解説】
・Rigidbodyのパラメータ gravityScale は重力の強さ、freezeRotation は回転するかどうかを決めることができます。自分がクリックされた瞬間に重力と回転を止め、離された瞬間に元に戻すことで移動中はオブジェクトが静止するようになります。
・Camera.main.ScreenToWorldPoint(Input.mousePosition) で、マウスのスクリーン座標をワールド座標に変換できます。
例えばクリックされた場所にオブジェクトを生成したい時などにも使えます。2Dゲームを作るときは特によく使うので覚えておきましょう。
・Rigidbodyの関数 MovePosition は引数の座標へ移動させる関数ですが、当たり判定の影響を受けます。これによって他のオブジェクトを貫通して移動できないようにしています。
最後にインスペクターから設定を行います。RigidBody2Dをpublicにしているので自身にアタッチされているRigidBody2Dをドラッグ&ドロップしてください。

EventTriggerを設定しましょう。
PointerDown(自分の上でクリックされた瞬間)でMoveStart関数を呼びます。
PointerUp(クリックが離された瞬間)でMoveEnd関数を呼びます。

ここまで設定できたら実行して、スプライトをドラッグで移動させてみてください。床を貫通して移動しないか確認してみましょう。
スプライトを何個も複製するとMovePosition関数の挙動がわかりやすいかと思います。

EventTriggerはゲームのシステムとしても、UIのクオリティを上げるためにも活用できるコンポーネントなのでぜひ組み込んでみましょう。
【サンプルで使用している画像】 Rド 様