【Unity】【UI Toolkit】Visual Elementのマウスによるクリック判定・範囲を制御する

UnityのUI ToolkitでVisual Elementのマウスによるクリック判定・範囲を制御する方法です。

Unity 2022.2.19

マウスイベントに反応しないようにする

VisualElement.pickingModePickingMode.Ignoreに設定すると、そのVisualElementはマウスイベントに反応しなくなります。
この挙動を確かめるために以下のように、マウスイベントに反応した場合にログ出力を行う、PickingModeIgnoreVisualElementを作成します。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        // マウスイベントに反応しないようにする
        pickingMode = PickingMode.Ignore;
    }

    protected override void ExecuteDefaultActionAtTarget(EventBase evt)
    {
        base.ExecuteDefaultActionAtTarget(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からウィンドウを開き、赤いVisual Elementをクリックすると、クリックイベントに反応しないことを確認できます。

反応しない

マウスイベントに反応する範囲を指定する

VisualElement.ContainsPointをオーバーライドすると、マウスイベントに反応する範囲をカスタムすることができます。
以下は、Paddingを除いた領域(ContentRect)のみマウスイベントに反応するVisualElementの例です。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        style.paddingLeft = 25;
        style.paddingRight = 25;
        style.paddingTop = 25;
        style.paddingBottom = 25;
    }

    protected override void ExecuteDefaultActionAtTarget(EventBase evt)
    {
        base.ExecuteDefaultActionAtTarget(evt);

        // クリックイベントが来たらログを出力
        if (evt.eventTypeId == MouseDownEvent.TypeId())
            Debug.Log("Mouse Down");
    }

    public override bool ContainsPoint(Vector2 localPoint)
    {
        // contentRect (paddingを除いた領域) のみをクリック判定に含める
        return contentRect.Contains(localPoint);
    }
}

Window > Exampleからウィンドウを開き、赤いVisual Elementをクリックすると、Paddingを除いた中央に近い部分のみクリックに反応することを確認できます。

参考

docs.unity3d.com