【Unity】【UI Toolkit】VisualElement.transformでUIアニメーションを実装する

UnityのUI ToolkitのVisualElement.transformでUIアニメーションを実装する方法についてまとめました。

Unity 2022.2.17

Transformとは?

UI Toolkitにおいては、Flexboxの概念に沿ったレイアウトシステムにより各Visual Elementの座標やサイズが自動計算されます。
UI BuilderではPositionやFlex、Sizeなどの項目によりこのレイアウトの設定を行うことができます。

レイアウト設定

これとは別に、Transformという項目があります。
これを設定するとVisual Elementを移動・スケーリング・回転、またその起点を設定することができます。

Transform

さてこのTransformによる変形は、Flexboxベースの自動レイアウトが行われた後に処理されます。
すなわち、自動レイアウトで決定された他のVisual Elementの座標などには影響しない形で、対象のVisual Elementだけを変形することができます。

対象だけ変形

また、レイアウトが再計算されないため処理負荷も軽いです。

これらの特性から、UIアニメーションを作る際にはこのTransformが有用です。
本記事ではこのTransformを使って簡単なUIアニメーションを実装してみます。

UI Builderで初期値を設定する

それではアニメーションを行う準備として、まずUI Builderでレイアウトを組んでTransformの項目に初期値を設定します。
今回は下図のように、緑のVisual ElementのTransformを(100, 50)に設定して移動させ、回転の起点となるOriginを左上に設定しました。

設定

なおこれらのプロパティはUSSで設定することもできます。
詳細は本記事では割愛しますが、以下のドキュメントに詳しく書かれているので必要に応じて参照してください。

docs.unity3d.com

スクリプトでアニメーションさせる

次にスクリプトを使ってこれをアニメーションさせます。

スクリプトによりTransformによる変形を行うには、以下のようにVisualElement.transformを書き換えます。

using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public sealed class Example : EditorWindow
{
    private const int DeltaTimeMillis = (int)(1.0f / 60.0f * 1000);
    [SerializeField] private VisualTreeAsset visualTree;

    private void CreateGUI()
    {
        visualTree.CloneTree(rootVisualElement);
        var green = rootVisualElement.Q<VisualElement>("Green");
        
        // アニメーションを開始
        var _ = RotateGreenAsync(green);
    }

    private static async Task RotateGreenAsync(VisualElement target)
    {
        while (true)
        {
            await Task.Delay(DeltaTimeMillis);
            
            // VisualElement.transformを使って回転させる
            target.transform.rotation *= Quaternion.Euler(Vector3.forward * 10.0f);
        }
    }

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

このスクリプトのInspectorから前節のUXMLをアサインし、実行すると下図の結果が得られます。

結果

正常にアニメーションしていることを確認できました。

localBoundとworldBoundとTransform

VisualElementにはlocalBoundworldBoundというプロパティがあります。

これはそれぞれ名前の通り、ローカル空間とワールド空間(EditorWindowだったらウィンドウ基準の空間)の座標情報を表します。

ただし、localBoundはTransformを適用する前の情報であるのに対し、worldBoundはTransformを適用した後の情報になります。
これらを使う際にはこの点に注意が必要です。

参考

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com