版本:Unity 6 (6000.0)
语言:英语
在编辑器和运行时 UI 中创建饼图
使用 Mesh API 创建径向进度指示器

使用 Vector API 创建径向进度指示器

版本: 2023.2+

此示例演示如何创建自定义控件并使用 Vector API 将视觉内容绘制到视觉元素视觉树中的一个节点,它实例化或派生自 C# VisualElement 类。您可以设置外观、定义行为,并将其显示在屏幕上作为 UI 的一部分。 更多信息
参见 术语表

示例概述

此示例创建了一个自定义控件,用于显示进度,作为进度条的替代方案。进度指示器在显示百分比的标签周围以部分填充的圆环显示进度值。它支持 0 到 100 之间的数值,该数值决定圆环填充的程度。

您可以在此 GitHub 存储库 中找到此示例创建的完整文件。

先决条件

本指南适用于熟悉 Unity 编辑器、UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三个 UI 系统。 更多信息
参见 术语表
工具包和 C# 脚本的开发人员。在开始之前,请熟悉以下内容

创建径向进度控件及其自定义网格

创建 C# 脚本以定义 RadialProgress 视觉元素,并创建 C# 脚本以定义自定义网格Unity 的主要图形基本类型。网格构成了 3D 世界的很大一部分。Unity 支持三角形或四边形多边形网格。Nurbs、Nurms、Subdiv 表面必须转换为多边形。 更多信息
参见 术语表
。使用 USS 文件设置视觉元素的样式。

  1. 使用任何模板创建一个 Unity 项目。
  2. 创建一个名为 radial-progress 的文件夹来存储您的文件。
  3. radial-progress 文件夹中,创建一个名为 RadialProgress.cs 的 C# 脚本,内容如下
using Unity.Collections;
using UnityEngine;
using UnityEngine.UIElements;

namespace MyGameUILibrary
{

    // An element that displays progress inside a partially filled circle
    [UxmlElement]
    public partial class RadialProgress : VisualElement
    {

        // 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
        [UxmlAttribute]
        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();
        }
    }
}

设置自定义控件的样式

创建一个名为 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);
    }

在 UI 文档中使用自定义控件并进行测试

使用 UI 生成器添加控件并应用 USS 样式表。使用不同的 Progress 值测试控件。

  1. 创建一个名为 RadialProgressExample.uxml 的 UI 文档。
  2. 双击 RadialProgressExample.uxml 以在 UI 生成器中打开它。
  3. 在库窗口中,选择 项目 > 自定义控件 > MyUILibrary
  4. RadialProgress 拖动到层次结构窗口。
  5. 在 UI 生成器的 样式表 部分中,添加 RadialProgress.uss 作为现有的 USS。
  6. 在层次结构窗口中,选择 RadialProgress
  7. 检查器一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。 更多信息
    参见 术语表
    窗口中,在 名称 框中输入 radial-progress
  8. 在检查器窗口中,在 进度 框中输入不同的值。视口用户在屏幕上看到应用程序的可见区域。
    参见 术语表
    中的百分比会发生变化,绿色进度环会调整大小。

创建逻辑以使用动态值更新进度

创建一个 C# MonoBehaviour 脚本,以使用动态值更新控件的 Progress 属性,以进行演示。在 radial-progress 文件夹中,创建一个名为 RadialProgressComponent.cs 的 C# MonoBehaviour,内容如下

using MyUILibrary;
using UnityEngine;
using UnityEngine.UIElements;

[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()
    {
        m_RadialProgress.progress = ((Mathf.Sin(Time.time) + 1.0f) / 2.0f) * 60.0f + 10.0f;
    }
}

在运行时测试进度指示器

  1. 在 Unity 中,选择 游戏对象 > UI 工具包 > UI 文档
  2. 在层次结构窗口中选择 UIDocument
  3. RadialProgressComponent.cs 作为 UIDocument 游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、航点等等。游戏对象的函数由附加到它的组件定义。 更多信息
    参见 术语表
    的组件添加。
  4. 进入播放模式。进度指示器将出现在场景场景包含游戏环境和菜单。可以将每个独特的场景文件视为一个独特的关卡。在每个场景中,您放置环境、障碍物和装饰,从本质上讲是设计和构建游戏的各个部分。 更多信息
    参见 术语表
    中,进度环和值会动态变化。

其他资源

在编辑器和运行时 UI 中创建饼图
使用 Mesh API 创建径向进度指示器