Migrate custom controls from an earlier version to Unity 6
Compare the conventional custom control authoring process with the new revamped workflow in Unity 6.
Read time 3 minutesLast updated 25 days ago
Unity 6 introduces improvements that simplify the creation of custom controls. This guide explains how to migrate custom controls from previous versions to Unity 6’s revamped workflow.
Old system
Previously, creating a custom control required using the class to define attributes. The following example demonstrates this approach for a control.
UxmlTraitsProgressBarThe examples focus on attribute authoring and don't include the behavior of the control. It creates a class that defines the attributes of the control. For each attribute, the class specifies the following:
UxmlTraitsProgressBar- Its type
- Default value
- Name
Then, it gets the value for each attribute and assigns it to the element. It also adds a class that creates instances of the element.
UxmlFactoryusing UnityEngine.UIElements;public class ProgressBar : VisualElement{ public new class UxmlFactory : UxmlFactory<ProgressBar, UxmlTraits> { } public new class UxmlTraits : BindableElement.UxmlTraits { UxmlFloatAttributeDescription m_LowValue = new UxmlFloatAttributeDescription { name = "low-value", defaultValue = 0 }; UxmlFloatAttributeDescription m_HighValue = new UxmlFloatAttributeDescription { name = "high-value", defaultValue = 100 }; UxmlFloatAttributeDescription m_Value = new UxmlFloatAttributeDescription { name = "value", defaultValue = 0 }; UxmlStringAttributeDescription m_Title = new UxmlStringAttributeDescription() { name = "title", defaultValue = string.Empty }; public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); var bar = ve as ProgressBar; bar.lowValue = m_LowValue.GetValueFromBag(bag, cc); bar.highValue = m_HighValue.GetValueFromBag(bag, cc); bar.value = m_Value.GetValueFromBag(bag, cc); bar.title = m_Title.GetValueFromBag(bag, cc); } } public string title { get; set; } public float lowValue { get; set; } public float highValue { get; set; } public float value { get; set; }}
Unity 6 system
Unity 6 simplifies custom control creation with the and attributes, eliminating the need for and . The new system streamlines the process by automatically handling the conversion of values to and from UXML attribute strings.
UxmlElementUxmlAttributeUxmlTraitsUxmlFactoryThe following shows the updated the example:
ProgressBarusing UnityEngine.UIElements;[UxmlElement]public partial class ProgressBar : VisualElement{ [UxmlAttribute] public string title { get; set; } [UxmlAttribute] public float lowValue { get; set; } [UxmlAttribute] public float highValue { get; set; } = 100; [UxmlAttribute] public float value { get; set; }}
Key changes
Here's the key changes:
- Use to declare a custom control.
UxmlElement - Mark the class as partial.
- Use to define attributes, removing the need for
UxmlAttribute.UxmlTraits - The UXML attribute name is automatically derived from the property name, but you can customize it.
UXML usage
The UXML usage remains the same for both systems:
<ui:UXML xmlns:ui="UnityEngine.UIElements"> <ProgressBar title="My Progress bar" low-value="0" high-value="1" value="0.5" /></ui:UXML>
Important considerations
If an element lacks the attribute, Unity defaults to the and systems for serialization. Ensure consistency by using a single serialization approach per visual element. While both systems can coexist in a UXML file, don't mix them with a single element.
UxmlElementUxmlTraitsUxmlFactoryAfter migrating to the new system, reimport UXML assets to match the updated code. While this process happens automatically, but any previously built Asset Bundles containing UXML files need to be rebuilt to function correctly.