Настраиваемые элементы управления
Содержание
UI Toolkit предлагает стандартный набор элементов для создания интерфейсов, но вы также можете создавать пользовательские элементы управления, адаптированные к потребностям вашего приложения.
Например, пользовательская шкала здоровья могла бы менять цвет в зависимости от значения здоровья, анимируясь от зеленого до желтого и красного при снижении здоровья. Она могла бы быть перенаправлена между персонажами без дополнительной настройки — или даже использоваться для представления других статистических данных, таких как манна или сила. Этот инкапсулированный элемент управления предлагал бы четкое визуальное обновление слайдера из стандартной библиотеки UI Toolkit.
Пользовательские элементы управления позволяют упаковать функциональность в самостоятельные элементы и переиспользовать их в разных частях интерфейса. Хорошо спроектированные элементы абстрактны, самодостаточны и способствуют повторному использованию кода, упрощая сопровождение проекта. Реализуя пользовательские элементы управления, не привязывайте их к конкретным компонентам, не работающим самостоятельно (например, к игровым меню).
Атрибут UxmlElement
Чтобы создать пользовательский контроллер, начните с определения нового скрипта C#, который наследует от VisualElement класс — или подкласс, наиболее близкий к тому, что вы хотите создать. Нужен элемент вроде кнопки? Просто унаследуйтесь от Button class.
Чтобы ваш пользовательский элемент управления стал доступен в UXML и UI Builder, добавьте к классу атрибут UxmlElement. Убедитесь, что элемент объявлен как открытый частичный класс:
[UxmlElement]
public partial class ExampleElement: VisualElement
{
}
Ваш пользовательский элемент управления затем появится в разделе Библиотеки под Таможенный элемент управления (C#) категории в UI Builder. Затем вы можете перетащить его в UI Builder’s Hierarchy окно.
Примечание: Поскольку визуальные элементы не являются GameObjects, они не имеют обычных событий жизненного цикла, таких как Awake, OnEnable, OnDisableи OnDestroy. Вместо этого вы инициализируете пользовательский контроллер с помощью его конструктора.
[UxmlElement]
public partial class ExampleElement: VisualElement
{
// Constructor
public ExampleElement()
{
// Initialization
}
}
Также можно отложить инициализацию до добавления пользовательского элемента управления в UI. Для этого зарегистрируйте обратный вызов для AttachToPanelEvent.
Чтобы обнаружить, что пользовательский контроллер удален из UI, используйте обратный вызов DetachFromPanelEvent.
Атрибут UxmlAttribute
Добавление UxmlAttribute атрибут к свойству делает его появляться в UI Builder’s Inspector окно. Это позволяет интерактивно устанавливать начальные значения. UxmlAttributes может быть полезным при работе с дизайнером, так как изменения в Inspector не требуют модифицировать код.
Примените атрибут UxmlAttribute к каждому свойству, которое вы хотите раскрыть. Вы также можете настроить имена атрибутов с помощью аргумента имя.
Выбор контроля в Hierarchy отобразит ваши пользовательские атрибуты в окне Inspector, позволяя вам настроить их напрямую.
Атрибуты декоратора могут модифицировать ваши пользовательские поля атрибутов так же, как и MonoBehaviours. Полезные атрибуты декоратора включают TextArea, Tooltip, Range, Header, Min, Multiline, Space и Delayed. Например, использование атрибута Range добавляет ползунок для выбора значений в диапазоне.
Вот базовый пример добавления атрибута UxmlElement в пользовательский контроллер, который включает два открытых свойства, использующих атрибут UxmlAttribute.
[UxmlElement]
public partial class ExampleElement: VisualElement
{
[UxmlAttribute(name:"my-text")]
public string myStringValue { get; set; }
[UxmlAttribute]
public int myIntValue { get; set; }
}
В этом примере MyStringValue появляется как «Мой текст» в Inspector с использованием параметра имя. И MyStringValue, и MyIntValue могут быть изменены в Inspector, когда экземпляр ExampleElement выбран в Hierarchy.
Примечание: До Unity 6, создание пользовательских контроллеров требовало реализации классов UxmlTraits и UxmlFactory, которые обрабатывали регистрацию атрибутов и экземплярирование объектов для пользовательских элементов.
Unity 6 упрощает создание пользовательских элементов, вводя атрибуты UxmlElement и UxmlAttribute. Эти атрибуты непосредственно открывают пользовательские элементы управления и свойства в UXML и UI Builder. Этот новый рабочий процесс уменьшает количество стандартного кода и ускоряет настройку элементов UI.
Пример: пользовательский переключатель слайда
Примером простого пользовательского контроля может быть слайд-переключатель, элемент, похожий на переключатель, представляющий булевое значение.
Это может предложить более захватывающий опыт, чем стандартный переключатель. Добавление дополнительной визуальной обратной связи, такие как анимированный переключатель, изменение цвета и динамический текст, может привести к более интуитивной UI.
Определение настраиваемого контроля
В проекте QuizU вы можете найти простую реализацию этого пользовательского контроля в сцене CustomControlsDemo. Откройте скрипт SlideToggle.cs, чтобы посмотреть, как он работает (фрагменты показаны ниже).
Пользовательский элемент управления «переключатель-слайдер» наследуется от наиболее подходящего базового класса — BaseField<bool> в этом случае. Атрибут UxmlElement раскрывает элемент управления в UXML и UI Builder, делая его повторно используемым.
[UxmlElement]
public partial class SlideToggle : BaseField<bool>
{
// …
[UxmlAttribute]
public string EnabledText { get; set; } = "Enabled";
[UxmlAttribute]
public string DisabledText { get; set; } = "Disabled";
[UxmlAttribute]
public Color EnabledBackgroundColor { get; set; } = new Color(0f, 0.5f, 0.85f,1f);
[UxmlAttribute]
public Color DisabledBackgroundColor { get; set; } = Color.gray;
}
Визуальная структура состоит из фона (m_Input) и кнопки (m_Knob), с классами USS, определяющими внешний вид.
public SlideToggle(string label) : base(label, new VisualElement())
{
AddToClassList(ussClassName);
m_Input = this.Q(className: BaseField<bool>.inputUssClassName);
m_Input.AddToClassList(inputUssClassName);
m_Input.name = "input";
m_Knob = new();
m_Knob.AddToClassList(inputKnobUssClassName);
m_Knob.name = "knob";
m_Input.Add(m_Knob);
labelElement.name = "label";
labelElement.text = (value) ? "enabled" : "disabled";
}
Обработка событий реализована так, чтобы реагировать на щелчки, нажатия клавиш и события навигации. Это позволяет менять состояние несколькими способами.
{
// …
RegisterCallback<ClickEvent>(evt => OnClick(evt));
RegisterCallback<KeyDownEvent>(evt => OnKeydownEvent(evt));
// …
}
static void OnClick(ClickEvent evt)
{
var slideToggle = evt.currentTarget as SlideToggle;
slideToggle.ToggleValue();
evt.StopPropagation();
}
static void OnKeydownEvent(KeyDownEvent evt)
{
var slideToggle = evt.currentTarget as SlideToggle;
if (slideToggle.panel?.contextType == ContextType.Player)
return;
if (evt.keyCode == KeyCode.KeypadEnter || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.Space)
{
slideToggle.ToggleValue();
evt.StopPropagation();
}
}
Цвет метки и фона обновляется автоматически, когда пользователь переключает переключатель, обеспечивая визуальную обратную связь.
Здесь мы используем SetValueWithoutNotify чтобы обновить визуальное состояние переключателя, не запуская ChangeEvent. Поскольку этот метод вызывается внутренне при изменении значения, UI обновляется правильно, не вызывая бесконечного цикла обновлений.
public override void SetValueWithoutNotify(bool newValue)
{
base.SetValueWithoutNotify(newValue);
m_Input.EnableInClassList(inputCheckedUssClassName, newValue);
m_Input.style.backgroundColor = newValue ? EnabledBackgroundColor : DisabledBackgroundColor;
labelElement.text = (value) ? EnabledText : DisabledText;
}
Исследуйте пример реализации в сцене CustomControlsDemo. Щёлкните элемент мышью либо нажмите Enter или пробел, чтобы переключить его активное состояние. В этом примере цвет метки и фона динамически обновляется, когда пользователь переключает slide toggle, а быстрая анимация даёт визуальную обратную связь.
С помощью Inspector задайте строковые метки и цвета фона, соответствующие включённому и отключённому состоянию.
Используйте переключатель слайдов
После компиляции, слайд переключатель теперь готов интегрировать в любой части вашего UI. Используйте пользовательские SlideToggle класс так же, как любой другой визуальный элемент. Вот пример реализации, использующей SlideToggle класс, чтобы отключить или включить звук:
// Example usage in a MonoBehaviour
public class MuteAudioToggle : MonoBehaviour
{
[SerializeField] AudioSettingsSO m_AudioSettingsSO;
[SerializeField] UIDocument m_Document;
void OnEnable()
{
var root = m_Document.rootVisualElement;
SlideToggle slideToggle = root.Q<SlideToggle>("master-audio-toggle");
if (slideToggle != null)
{
slideToggle.value = !m_AudioSettingsSO.IsMasterMuted;
slideToggle.RegisterValueChangedCallback(evt => m_AudioSettingsSO.IsMasterMuted =
!evt.newValue);
}
}
}
В этом случае SlideToggle является частью существующего документа UXML. MonoBehaviour находит его по имени в визуальном дереве, а затем использует метод RegisterValueChangedCallback чтобы связать состояние переключателя с настройками звука.
Так как SlideToggle является самостоятельным пользовательским элементом, вы можете использовать его для любого вида переключателя в вашем UI. Например, в UI Toolkit — Драконы образце, аналогичный SlideToggle включает и отключает счетчик fps.
Настройте SlideToggle в соответствии с требованиями вашего приложения – он идеально подходит для настройки визуальных эффектов, звука или параметров игры. Создайте его один раз, а затем повторно используйте его там, где пользовательский переключатель может улучшить пользовательский опыт.
Для полной реализации см. скрипт SlideToggle.cs в проекте QuizU.
Создание дополнительных настраиваемых элементов управления
Если в стандартной библиотеке UI Toolkit нет контроля, вы можете создать свой собственный. Вот несколько примеров, которые помогут вам подумать о том, как можно развернуть пользовательский контроль в своих собственных играх:
Полосы здоровья и индикаторы прогресса: Game атрибуты, такие как здоровье, мана, мощность и т.д. могут сильно варьироваться в зависимости от игры, что делает их отличными кандидатами для настраиваемого управления. Выставьте UxmlAttributes как максимальное значение, текущее значение и цвета статуса, чтобы добавить опции для цветовых градиентов.
Рейтинг звезд: Этот контроллер функционирует как сегментированная шкала прогресса, представляющая целое число (e.g. звезды за завершение уровня). Начните с визуального элемента с несколькими дочерними элементами, которые могут переключаться между заполненными и незаполненными состояниями. Выставьте int с максимальным значением в Inspector и позвольте пользователю настроить изображения спрайтов с помощью UxmlAttributes.
Управление видом вкладок: Интерфейс с вкладками — распространённый способ переключаться между разными представлениями или разделами внутри одного окна. Реализуйте его, создав собственный элемент с рядом вкладок и областью содержимого. Каждая вкладка может быть визуальным элементом в виде кнопки, а вкладки можно добавлять и убирать динамически.
Помните, что в большинстве случаев, вы также можете запустить USS переходы, чтобы добавить визуальный вкус с анимацией. С помощью пользовательских контроля, ваши пользователи могут прижать, щелкнуть, прокрутить и переключаться через вашу уникальную игру UIs.
Мы не можем дождаться, чтобы увидеть, что вы делаете с ними.