【Unity】【UI Toolkit】レイアウトが変更された時に呼ばれるGeometryChangedEventの使い方

UnityのUI Toolkitでレイアウトが変更された時に呼ばれるGeometryChangedEventの使い方についてまとめました。

Unity 2022.2.17

GeometryChangedEventとは?

GeometryChangedEventを使うと、対象のVisualElementのレイアウトが変更された時のコールバックを取得できます。

コールバックの登録方法は他のイベントと同様、RegisterCallbackメソッドを使います。

VisualElement element;
element.RegisterCallback<GeometryChangedEvent>(evt =>
{
    // elementのレイアウトが変更されたときの処理
});

なおUI Toolkitのレイアウトシステムに関しては以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

使ってみる

これを使って、EditorWindowのサイズが変わった時に、そのサイズに合わせるように正方形を描画するスクリプトを書いてみます。

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public sealed class Example : EditorWindow
{
    private const int Margin = 10;
    private VisualElement _squareElement;

    private void CreateGUI()
    {
        // ウィンドウサイズに合わせたサイズを持つ親要素を生成
        var parentElement = new VisualElement();
        parentElement.style.backgroundColor = new Color(0.75f, 0.0f, 0.0f);
        parentElement.style.width = new StyleLength(new Length(100, LengthUnit.Percent));
        parentElement.style.height = new StyleLength(new Length(100, LengthUnit.Percent));
        rootVisualElement.Add(parentElement);

        // 正方形の要素を生成
        var squareElement = new VisualElement();
        _squareElement = squareElement;
        squareElement.style.backgroundColor = new Color(0.0f, 0.0f, 0.75f);
        squareElement.style.marginBottom = Margin;
        squareElement.style.marginLeft = Margin;
        squareElement.style.marginRight = Margin;
        squareElement.style.marginTop = Margin;
        parentElement.Add(squareElement);

        // parentElementのサイズが変更されたときのコールバックを登録
        parentElement.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);

        ResizeSquareElement();
    }

    private void OnGeometryChanged(GeometryChangedEvent evt)
    {
        ResizeSquareElement();
    }

    // squareElementのサイズを、正方形を保ったまま親要素のサイズに合わせる
    private void ResizeSquareElement()
    {
        var parentSize = _squareElement.parent.layout.size;
        var size = parentSize.x > parentSize.y ? parentSize.y : parentSize.x;
        size -= Margin * 2;
        _squareElement.style.width = size;
        _squareElement.style.height = size;
    }

    [MenuItem("Window/Example")]
    public static void ShowWindow()
    {
        GetWindow<Example>();
    }
}

説明はコメントに書いた通りです。

ウィンドウサイズと連動する親要素のレイアウトを監視し、変更が加わったタイミングで正方形の要素のサイズも変更しています。

実行結果

Window > Exampleからウィンドウを開いて上記のスクリプトを実行すると結果は下図の通りとなります。

実行結果

狙い通り正方形のサイズが変わっていることを確認できました。

関連

light11.hatenadiary.com

参考

docs.unity3d.com