【Unity】UIイベントをスクリプトで簡単に検知する拡張メソッド

f:id:halya_11:20180131233141p:plain:w300

UnityのUIはクリック以外にも、ドラッグなどいろんなイベントを検知できます。 それらのイベント検知をスクリプトから簡単に扱うための拡張メソッドを作ってみます。

インスペクタからイベントを登録する

まずインスペクタからイベントを登録する場合には、
検知したいUIに EventTrigger をアタッチしてから AddNewEventType をクリックします。

f:id:halya_11:20180131233141p:plain:w300

この辺りは下記の記事が詳しいです。 qiita.com

スクリプトからイベントを登録する

上記のようなイベントの登録をスクリプトから行うには次のようにします。

using UnityEngine;
using UnityEngine.EventSystems;

public class AddEventListener : MonoBehaviour {

    private void Awake(){

        var trigger = GetComponent<EventTrigger>();
        var entry = new EventTrigger.Entry();
        entry.eventID = EventTriggerType.PointerClick;
        entry.callback = new EventTrigger.TriggerEvent();
        entry.callback.AddListener(data => { /* 処理 */ });
        trigger.triggers.Add(entry);
    }
}

ただ、イベント検知するためにこんなに冗長なコードを書いていられないので拡張メソッドを作ります。

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Events;

public static class UIBehaviourExtensions {

    public static void AddPointerClickListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
        ui.AddEventListener(EventTriggerType.PointerClick, callback);
    }

    public static void RemoveListener(this UIBehaviour ui, EventTrigger.Entry entry){
        var trigger = ui.gameObject.GetOrAddComponent<EventTrigger>();
        if (trigger.triggers.Contains(entry)) {
            trigger.triggers.Remove(entry);
        }
    }

    public static EventTrigger.Entry AddEventListener<T>(this UIBehaviour ui, EventTriggerType triggerType, System.Action<T> callback) where T : BaseEventData{
        var trigger = ui.gameObject.GetOrAddComponent<EventTrigger>();
        var entry = new EventTrigger.Entry();
        entry.eventID = triggerType;
        entry.callback = new EventTrigger.TriggerEvent();
        entry.callback.AddListener(data => callback(data as T));
        trigger.triggers.Add(entry);
        return entry;
    }
        
    private static T GetOrAddComponent<T> (this GameObject obj) where T : Component
    {
        var comp = obj.GetComponent<T>();
        return comp ?? (comp = obj.AddComponent<T>());
    }
}

こんな感じでしょうか。
ドラッグなど他のイベントも使いたければ、同じように足しておきます。

public static void AddPointerDownListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
    ui.AddEventListener(EventTriggerType.PointerDown, callback);
}

public static void AddPointerUpListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
    ui.AddEventListener(EventTriggerType.PointerUp, callback);
}

public static void AddBeginDragListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
    ui.AddEventListener(EventTriggerType.BeginDrag, callback);
}

public static void AddDragListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
    ui.AddEventListener(EventTriggerType.Drag, callback);
}

public static void AddEndDragListener(this UIBehaviour ui, System.Action<PointerEventData> callback){
    ui.AddEventListener(EventTriggerType.EndDrag, callback);
}

使い方

使い方はシンプル。

UIBehaviour ui;
ui.AddPointerClickListener(data => { /* 処理 */ });