
【Unity】2Dオブジェクトにクリックとかドラッグをできるようにする
前回記事
https://note.com/woworora/n/nfc1765328c7a
Unityを積むことはや数か月。イベントの取り扱いすら忘れたので手っ取り早く忘備録を書く。
思い出しがてら、UIオブジェクトに実装したイベントコンポーネントを2Dに移植してみた。
基本のスクリプト
まずは任意の2Dオブジェクトに以下のスクリプトと2D Colliderをアタッチする。EventSystemの作成も忘れずに。
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class InteractiveObject: MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler, IPointerDownHandler
{
new public Transform transform; // オブジェクトのTransform
protected virtual void Awake()
{
transform = GetComponent<Transform>();
}
public Action<InteractiveObject, PointerEventData> OnClickAction;
public Action<InteractiveObject, PointerEventData> OnPointerEnterAction;
public Action<InteractiveObject, PointerEventData> OnPointerExitAction;
public Action<InteractiveObject, PointerEventData> OnBeginDragAction;
public Action<InteractiveObject, PointerEventData> OnDragAction;
public Action<InteractiveObject, PointerEventData> OnEndDragAction;
public Action<InteractiveObject, PointerEventData> OnDropAction;
public Action<InteractiveObject, PointerEventData> OnPointerDownAction;
public void ResetAllActions()// すべてのイベントアクションを空のラムダ式にリセットする
{
OnClickAction = null;
OnPointerEnterAction = null;
OnPointerExitAction = null;
OnBeginDragAction = null;
OnDragAction = null;
OnEndDragAction = null;
OnDropAction = null;
OnPointerDownAction = null;
}
public void OnPointerClick(PointerEventData eventData)
{
OnClickAction?.Invoke(this, eventData);
}
public void OnPointerEnter(PointerEventData eventData)
{
OnPointerEnterAction?.Invoke(this, eventData);
}
public void OnPointerExit(PointerEventData eventData)
{
OnPointerExitAction?.Invoke(this, eventData);
}
public void OnBeginDrag(PointerEventData eventData)
{
OnBeginDragAction?.Invoke(this, eventData);
}
public void OnDrag(PointerEventData eventData)
{
OnDragAction?.Invoke(this, eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
OnEndDragAction?.Invoke(this, eventData);
}
public void OnDrop(PointerEventData eventData)
{
OnDropAction?.Invoke(this, eventData);
}
public void OnPointerDown(PointerEventData eventData)
{
OnPointerDownAction?.Invoke(this, eventData);
}
}
クリックとドラッグのイベント作成
今回は個別のスクリプトを書いて、それぞれアタッチすることで実装した。
オブジェクトに対する操作が常に同じなら、分かりやすくて管理しやすいかも。
// クリックしたらOnOffを切り替える。前回記事の機能
using System;
using UnityEngine;
using UnityEngine.EventSystems;
public class ExmSwitch : MonoBehaviour
{
public InteractiveObject obj;
void Start()
{
obj.OnClickAction = (obj, eventData) => buttonOn();
}
public void buttonOn()
{
obj.OnClickAction = (obj, eventData) => buttonOff();
Debug.Log("buttonOn");
}
public void buttonOff()
{
obj.OnClickAction = (obj, eventData) => buttonOn();
Debug.Log("buttonOff");
}
}
// Dragしたらマウスにオブジェクトを追従させる。離したら元の座標に戻る。
using System;
using UnityEngine;
using UnityEngine.EventSystems;
public class ExmDrag : MonoBehaviour
{
public InteractiveObject obj;
private Vector3 defaultPosition;
void Start()
{
// 初期位置を保存
obj.OnBeginDragAction = (obj, eventData) => setDefaultPosition();
obj.OnDragAction = (obj, eventData) => drag(eventData);
obj.OnEndDragAction = (obj, eventData) => resetPosition();
}
private void drag(PointerEventData eventData)
{
// マウス位置を取得してオブジェクトの位置を更新
Vector3 mousePosition = Input.mousePosition;
// マウス座標をワールド座標に変換
mousePosition.z = Camera.main.WorldToScreenPoint(obj.transform.position).z; // 元のオブジェクトのZ座標を保持
Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition);
// オブジェクトの位置を更新
obj.transform.position = worldPosition;
}
private void setDefaultPosition()
{
defaultPosition = obj.transform.position;
}
private void resetPosition()
{
obj.transform.position = defaultPosition;
}
}
