Version: 2022.3
言語: 日本語
エディターとランタイム UI で円グラフを作成する
Mesh API を使って放射状の進捗インジケーターを作成する

Vector API を使用して放射状の進捗インジケーターを作成する

バージョン: 2022.1 以降

この例では、カスタムコントロールを作成し、Vector API を使用してビジュアル要素にビジュアルコンテンツを描画する方法を示します。

例の概要

この例では、ローディングバーの代わりに進行状況を表示するカスタムコントロールを作成します。進捗インジケーターは、パーセンテージを表示するラベルの周囲に、部分的に塗りつぶされた輪で進捗値を表示します。0 から 100 までの値で表示され、それにより輪がどの程度塗りつぶされるかが決定されます。

この例で作成するすべてのファイルは、GitHub リポジトリ にあります。

要件

このガイドは、Unity エディター、UI Toolkit、および C# スクリプトに精通している開発者を対象としています。始める前に、以下をよく理解してください。

放射状の進捗コントロールとそのカスタムメッシュを作成する

RadialProgress ビジュアル要素を定義する C# スクリプトとカスタムメッシュを定義する C# スクリプトを作成します。USS ファイルでビジュアル要素をスタイルを設定します。

  1. 任意のテンプレートで Unity プロジェクトを作成します。

  2. radial-progress というフォルダーを作成し、ファイルを保存します。

  3. radial-progressフォルダーに、以下のコンテンツを持つ RadialProgress.cs という名の C#スクリプトを作成します。

    using Unity.Collections;
    using UnityEngine;
    using UnityEngine.UIElements;
    
    namespace MyUILibrary
    {
    
        // An element that displays progress inside a partially filled circle
        public class RadialProgress : VisualElement
        {
            public new class UxmlTraits : VisualElement.UxmlTraits
            {
                // The progress property is exposed to UXML.
                UxmlFloatAttributeDescription m_ProgressAttribute = new UxmlFloatAttributeDescription()
                {
                    name = "progress"
                };
    
                // Use the Init method to assign the value of the progress UXML attribute to the C# progress property.
                public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
                {
                    base.Init(ve, bag, cc);
    
                    (ve as RadialProgress).progress = m_ProgressAttribute.GetValueFromBag(bag, cc);
                }
            }
    
            // Define a factory class to expose this control to UXML.
            public new class UxmlFactory : UxmlFactory<RadialProgress, UxmlTraits> { }
    
            // These are USS class names for the control overall and the label.
            public static readonly string ussClassName = "radial-progress";
            public static readonly string ussLabelClassName = "radial-progress__label";
    
            // These objects allow C# code to access custom USS properties.
            static CustomStyleProperty<Color> s_TrackColor = new CustomStyleProperty<Color>("--track-color");
            static CustomStyleProperty<Color> s_ProgressColor = new CustomStyleProperty<Color>("--progress-color");
    
            Color m_TrackColor = Color.gray;
            Color m_ProgressColor = Color.red;
    
            // This is the label that displays the percentage.
            Label m_Label;
    
            // This is the number that the Label displays as a percentage.
            float m_Progress;
    
            // A value between 0 and 100
            public float progress
            {
                // The progress property is exposed in C#.
                get => m_Progress;
                set
                {
                    // Whenever the progress property changes, MarkDirtyRepaint() is named. This causes a call to the
                    // generateVisualContents callback.
                    m_Progress = value;
                    m_Label.text = Mathf.Clamp(Mathf.Round(value), 0, 100) + "%";
                    MarkDirtyRepaint();
                }
            }
    
            // This default constructor is RadialProgress's only constructor.
            public RadialProgress()
            {
                // Create a Label, add a USS class name, and add it to this visual tree.
                m_Label = new Label();
                m_Label.AddToClassList(ussLabelClassName);
                Add(m_Label);
    
                // Add the USS class name for the overall control.
                AddToClassList(ussClassName);
    
                // Register a callback after custom style resolution.
                RegisterCallback<CustomStyleResolvedEvent>(evt => CustomStylesResolved(evt));
    
                // Register a callback to generate the visual content of the control.
                generateVisualContent += GenerateVisualContent;
    
                progress = 0.0f;
            }
    
            static void CustomStylesResolved(CustomStyleResolvedEvent evt)
            {
                RadialProgress element = (RadialProgress)evt.currentTarget;
                element.UpdateCustomStyles();
            }
    
            // After the custom colors are resolved, this method uses them to color the meshes and (if necessary) repaint
            // the control.
            void UpdateCustomStyles()
            {
                bool repaint = false;
                if (customStyle.TryGetValue(s_ProgressColor, out m_ProgressColor))
                    repaint = true;
    
                if (customStyle.TryGetValue(s_TrackColor, out m_TrackColor))
                    repaint = true;
    
                if (repaint)
                    MarkDirtyRepaint();
            }
    
            void GenerateVisualContent(MeshGenerationContext context)
            {
                float width = contentRect.width;
                float height = contentRect.height;
    
                var painter = context.painter2D;
                painter.lineWidth = 10.0f;
                painter.lineCap = LineCap.Butt;
    
                // Draw the track
                painter.strokeColor = m_TrackColor;
                painter.BeginPath();
                painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f, 0.0f, 360.0f);
                painter.Stroke();
    
                // Draw the progress
                painter.strokeColor = m_ProgressColor;
                painter.BeginPath();
                painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f, -90.0f, 360.0f * (progress / 100.0f) - 90.0f);
                painter.Stroke();
            }
        }
    }
    

UI Document でカスタムコントロールを使用しテストする

放射状進捗インジケーターカスタムコントロールのスタイルを設定するための USS ファイルを作成します。UI Builder を使用してコントロールを加え、USS スタイルシートを適用します。さまざまな Progress 値でコントロールをテストします。

  1. 以下のコンテンツで RadialProgress.uss という名の USS ファイルを作成します。

    .radial-progress {
        min-width: 26px;
        min-height: 20px;
        --track-color: rgb(130, 130, 130);
        --progress-color: rgb(46, 132, 24);
        --percentage-color: white;
        margin-left: 5px;
        margin-right: 5px;
        margin-top: 5px;
        margin-bottom: 5px;
        flex-direction: row;
        justify-content: center;
        width: 100px; 
        height: 100px;
    }
    
    .radial-progress__label {
        -unity-text-align: middle-left;
        color: var(--percentage-color);
    }
    
  2. RadialProgressExample.uxml という名前の UI Document を作成します。

  3. RadialProgressExample.uxml をダブルクリックして UI Builder で開きます。

  4. Library ウィンドウで、Project > Custom Controls > MyUILibrary を選択します。

  5. RadialProgress を Hierarchy ウィンドウにドラッグします。

  6. UI Builder の StyleSheets セクションに、既存の USS としてRadialProgress.uss を加えます。

  7. Hierarchy ウィンドウで、RadialProgress を選択します。

  8. Inspector ウィンドウの Name フィールドに radial-progress と入力します。

  9. Inspector ウィンドウで、Progress フィールドにさまざまな値を入力します。Viewport のパーセンテージが変わり、緑色の進捗リングのサイズが変化します。

ランタイムに進捗インジケーターを使用する

シーンで UI Document を使用し、デモ用にコントロールのProgress プロパティを動的な値で更新する C# MonoBehaviour スクリプトを作成します。

  1. radial-progress フォルダーに、以下のコンテンツを含む RadialProgressComponent.cs という C# スクリプトを作成します。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UIElements;
    using MyUILibrary;
    
    [RequireComponent(typeof(UIDocument))]
    public class RadialProgressComponent : MonoBehaviour
    {
    
        RadialProgress m_RadialProgress;
    
        void Start()
        {
            var root = GetComponent<UIDocument>().rootVisualElement;
    
            m_RadialProgress = new RadialProgress() {
                style = {
                    position = Position.Absolute,
                    left = 20, top = 20, width = 200, height = 200
                }
            };
    
            root.Add(m_RadialProgress);
        }
    
        void Update()
        {
            // For demo purpose, give the progress property dynamic values.
            m_RadialProgress.progress = ((Mathf.Sin(Time.time) + 1.0f) / 2.0f) * 60.0f + 10.0f;
        }
    }
    
  2. Unity で、GameObject > UI Toolkit > UI Document を選択します。

  3. Hierarchy ウィンドウで UIDocument を選択します。

  4. UIDocument ゲームオブジェクトのコンポーネントとして RadialProgressComponent.cs を加えます。

  5. 再生モードに入ります。シーンに進捗インジケーターが表示され、進捗リングと値が動的に変化します。

その他の参考資料

エディターとランタイム UI で円グラフを作成する
Mesh API を使って放射状の進捗インジケーターを作成する