【Unity】【UI Toolkit】独自のVisual ElementにDefault Actionを使ってイベントターゲットになった時の処理を定義する

UnityのUI Toolkitで独自のVisual ElementにDefault Actionを使ってイベントターゲットになった時の処理を定義する方法です。

Unity 2022.2.19

Default Actionとは?

たとえばトグルのようなUIを作ることを考えた時、UIがクリックされた時にON/OFF状態を切り替える必要があります。
このように、イベントに対するVisual Elementのデフォルト挙動をUI ToolkitではDefault Actionと呼びます。

本記事ではこのDefault Actionの定義の仕方についてまとめます。
なおUI Toolkitのイベント伝播の仕組みが前提知識となりますので、必要に応じて以下の記事を参照してください。

light11.hatenadiary.com

Default Actionの定義方法

Default Actionを定義するには、VisualElementを継承したクラスでExecuteDefaultActionをオーバーライドします。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    protected override void ExecuteDefaultAction(EventBase evt)
    {
        base.ExecuteDefaultAction(evt);

        if (evt.eventTypeId == MouseDownEvent.TypeId())
            Debug.Log("Mouse Down");
    }
}

マウス押下イベントのターゲットになった際にログ出力するようにしました。
動作確認のためにこれを適当なEditorWindow上に表示してみます。

using UnityEditor;
using UnityEngine;

public sealed class ExampleWindow : EditorWindow
{
    private void OnEnable()
    {
        var element = new ExampleElement();
        element.style.backgroundColor = Color.red;
        element.style.width = 100;
        element.style.height = 100;
        rootVisualElement.Add(element);
    }

    [MenuItem("Window/Example")]
    private static void Open()
    {
        GetWindow<ExampleWindow>();
    }
}

Window > Exampleからウィンドウを開き、赤い要素をクリックするとログ出力が行われることを確認できます。

赤い要素

ターゲットフェーズでDefault Actionを実行する

さて、上記のExecuteDefaultActionは、イベントのバブルアップフェーズの後、つまり一番最後に実行されます。

これに対して、代わりにExecuteDefaultActionAtTargetを使うと、その処理はトリクルダウンフェーズの直後、つまりターゲットフェーズで呼ばれます。
これは、バブルアップフェーズ以降に処理を伝播したくない場合に有用です。
以下のようにStopPropegationと併用すると、ターゲットフェーズでイベントの伝播を止めることができます。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    protected override void ExecuteDefaultActionAtTarget(EventBase evt)
    {
        base.ExecuteDefaultActionAtTarget(evt);

        if (evt.eventTypeId == MouseDownEvent.TypeId())
            Debug.Log("Mouse Down");

        // イベントの伝播を止める
        evt.StopPropagation();
    }
}

参考

docs.unity3d.com