【Unity】【UI Toolkit】Painter2Dを使ってベクターグラフィックスを描く(基礎編)

UnityのUI ToolkitでPainter2Dを使ってベクターグラフィックスを描画する方法についてまとめました。

Unity 2022.2.19

Painter2Dとは?

UI Toolkitでは、以下の記事のようにMeshGenerationContextを使って任意のメッシュを作成してUIを描画することができます。

light11.hatenadiary.com

Painter2Dは内部的にこれを使用した、ベクターグラフィックスを簡単に扱うための機能です。

本記事ではこのPainter2Dの概要と、簡単な使い方について紹介します。

なおPainter2DはUnity2022.1から使えます。

直線を描画する

まず、Painter2Dの基本的な使い方として、直線を描画するスクリプトを書いてみます。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        generateVisualContent += OnGenerateVisualContent;
    }

    private static void OnGenerateVisualContent(MeshGenerationContext context)
    {
        // painter2DのインスタンスをMeshGenerationContextから取得する
        var painter = context.painter2D;

        // 線の色を設定
        painter.strokeColor = Color.blue;
        // 線の太さを設定
        painter.lineWidth = 20;

        // パスを開始
        painter.BeginPath();

        painter.MoveTo(new Vector2(100, 100)); // 100, 100に移動
        painter.LineTo(new Vector2(200, 200)); // 200, 200まで直線でパスを繋ぐ
        painter.LineTo(new Vector2(300, 100)); // 300, 100まで直線でパスを繋ぐ

        // ClosePathを呼ぶとパスを閉じれる
        //painter.ClosePath();

        // パスに沿って線を引く
        painter.Stroke();
    }
}

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

Painter2DのインスタンスMeshGenerationContextから取得できるので、これを使ってLineToで2本の直線を描画しています。

動作確認

次に動作確認のために前節のUIを描画するためのEditor Windowを作成します。

using UnityEditor;

public sealed class ExampleWindow : EditorWindow
{
    public void CreateGUI()
    {
        var element = new ExampleElement();
        element.style.width = 1000;
        element.style.height = 1000;
        rootVisualElement.Add(element);
    }

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

Window > Exampleからこのウィンドウを開くと下図のような結果が得られます。

結果

設定した通りに直線が描画できていることを確認できました。

線の端や結合部分の形状を設定する

次に直線の端の形状や、直線同士が繋がる部分の形状を設定します。
これには以下のようにlineJoinlineCapを使用します。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        generateVisualContent += OnGenerateVisualContent;
    }

    private static void OnGenerateVisualContent(MeshGenerationContext context)
    {
        var painter = context.painter2D;

        painter.strokeColor = Color.blue;
        painter.lineWidth = 20;
        painter.lineJoin = LineJoin.Round; //LineJoinを設定
        painter.lineCap = LineCap.Round; // LineCapを設定
        painter.BeginPath();
        painter.MoveTo(new Vector2(100, 100));
        painter.LineTo(new Vector2(200, 200));
        painter.LineTo(new Vector2(300, 100));
        painter.Stroke();
    }
}

Window > Exampleから動作確認を行うと下図のような結果が得られます。

結果

各設定による効果は以下の図がわかりやすいです。

https://forum.unity.com/threads/introducing-the-vector-api-in-unity-2022-1.1210311/より引用

塗りつぶす

次に線を描画する代わりに塗りつぶしを行います。

塗りつぶしを行うにはStrokeの代わりにFillを使います。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        generateVisualContent += OnGenerateVisualContent;
    }

    private static void OnGenerateVisualContent(MeshGenerationContext context)
    {
        var painter = context.painter2D;

        // 塗りつぶしの色を設定
        painter.fillColor = Color.green;

        painter.BeginPath();
        painter.MoveTo(new Vector2(100, 100)); // 100, 100に移動
        painter.LineTo(new Vector2(200, 200)); // 200, 200まで直線でパスを繋ぐ
        painter.LineTo(new Vector2(300, 100)); // 300, 100まで直線でパスを繋ぐ

        // 塗りつぶす
        painter.Fill();
    }
}

Window > Exampleから動作確認を行うと下図のような結果が得られます。

塗りつぶし

正常に塗りつぶしが行われていることを確認できました。

円を描画する

次に直線ではなく円を描画してみます。

円を描画するにはArcメソッドを使います。

using UnityEngine;
using UnityEngine.UIElements;

public sealed class ExampleElement : VisualElement
{
    public ExampleElement()
    {
        generateVisualContent += OnGenerateVisualContent;
    }

    private static void OnGenerateVisualContent(MeshGenerationContext context)
    {
        var painter = context.painter2D;
        painter.fillColor = Color.red;

        painter.BeginPath();

        // 300, 300を中心とした半径100の半円を引く
        painter.Arc(new Vector2(300, 300), 100, Angle.Degrees(0), Angle.Degrees(180));

        painter.Fill();
    }
}

結果は以下のとおりです。

曲線を描画する

Painter2Dには上記の他にベジェ曲線を描画する機能があります。

これについては少々複雑になるので、別の記事にまとめます。

関連

light11.hatenadiary.com

参考

docs.unity3d.com

forum.unity.com