Используйте Painter2D API для создания радиального индикатора прогресса
Версия: 2023.2+
В этом примере показано, как создать пользовательские элементы управления и использовать Painter2D API для рисования визуального контента на визуальный элемент.
Примерный обзор
В этом примере создается пользовательский контроллер, отображающий прогресс, в качестве альтернативы строке загрузки. Индикатор прогресса отображает значение прогресса в частично заполненном кольце вокруг метки, отображающей процент. Он поддерживает значение от 0 до 100, которое определяет, насколько кольцо заполнено.
Вы можете найти завершенные файлы, созданные этим примером, в хранилище GitHub.
Предварительные условия
Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:
Создание радиального контроля прогресса и его пользовательской сетки
Создайте скрипт C# для определения визуального элемента RadialProgress и скрипт C# для определения пользовательской сетки. Стиль визуального элемента в файле USS.
- Создайте проект Unity с любым шаблоном.
- Создайте папку
radial-progressдля хранения ваших файлов. - В папке
radial-progressсоздайте скрипт C# с именемRadialProgress.csсо следующим содержанием:
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();
}
}
}
Стиль настраиваемого контроля
Создайте файл USS с именем RadialProgress.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 Builder для добавления элемента управления и применения таблицы стилей USS. Проверьте элемент управления с различными значениями Progress.
- Создать UI Документ с именем
RadialProgressExample.uxml. - Дважды щелкните
RadialProgressExample.uxml, чтобы открыть его в UI Builder. - В окне Библиотека выберите Project > Пользовательские элементы управления > UxmlSerializedData > MyUILibrary.
- Перетащите RadialProgress в окно Hierarchy.
- В разделе StyleSheets UI Builder добавить
RadialProgress.ussв качестве существующего USS.. - В окне Hierarchy выберите RadialProgress.
- В окне Inspector введите
radial-progressв поле Имя. - В окне Inspector введите различные значения в поле Прогресс. Процент в окне Видовой проем изменяется, и зеленое кольцо прогресса изменяет размер.
Создание логики для обновления прогресса с динамическими значениями
Создайте скрипт C# MonoBehaviour для обновления свойства Progress управления динамическими значениями для демонстрационных целей. В папке radial-progress создайте скрипт C# MonoBehaviour с именем RadialProgressComponent.cs со следующим содержанием:
using MyUILibrary;
using UnityEngine;
using UnityEngine.UIElements;
[RequireComponent(typeof(UIDocument))]
public class RadialProgressComponent : MonoBehaviour
{
RadialProgress m_RadialProgress;
void OnEnable()
{
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;
}
}
Проверка индикатора прогресса во время выполнения
- В Unity выберите GameObject > UI Toolkit > UI Документ.
- Выберите UIDocument в окне Hierarchy.
- Добавить RadialProgressComponent.cs в качестве компонента UIDocument GameObject.
- Введите режим воспроизведения. Индикатор прогресса появляется в сцене, и кольцо прогресса и значение изменяются динамически.