うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】IEventSystemHandler を持つコンポーネントがオブジェクトに複数あった場合の挙動

IEventSystemHandler を持つコンポーネントがオブジェクトに複数あった場合
どういった挙動になるのか気になったので

ボタンと下記コンポーネントを同じオブジェクトに追加して
どんなログが出るかを確認する

f:id:hacchi_man:20210112010140p:plain:w300

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

public class SampleMonoBehaviour : MonoBehaviour, IPointerDownHandler
{
    [SerializeField]
    private Button _button;

    private void Awake()
    {
        _button.onClick.AddListener(() => Debug.LogWarning("Click"));
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        Debug.LogWarning("Down");
    }
}

結果

同じオブジェクトに、同じ interface を持つコンポーネントがあってもどちらも呼ばれることが確認できた

f:id:hacchi_man:20210112010237p:plain:w300

コードを見てみる

EventSystems の伝播処理をしているクラスは下記で

uGUI/ExecuteEvents.cs at 135661e057d2a45f5b5b73ea48fb67a445816f61 · Unity-Technologies/uGUI · GitHub

実際にイベントを実行しているメソッドがこちら

        /// <summary>
        /// Bubble the specified event on the game object, figuring out which object will actually receive the event.
        /// </summary>
        public static GameObject GetEventHandler<T>(GameObject root) where T : IEventSystemHandler
        {
            if (root == null)
                return null;

            Transform t = root.transform;
            while (t != null)
            {
                if (CanHandleEvent<T>(t.gameObject))
                    return t.gameObject;
                t = t.parent;
            }
            return null;
        }

Raycast がヒットしたオブジェクトから、対象の IEventSystemHandler が持つコンポーネントがあるかを確認して
なければ親を探すという作りになっている

対象の IEventSystemHandler を確認する際に GetComponents をしているため、そのオブジェクトが複数の IEventSystemHandler
をもっていてもすべて実行されるということでした