UXML files are text files that define the logical structure of the user interface. The format used in UXML files is inspired by HTML (HyperText Markup Language), XAML (eXtensible Application Markup Language), and XML (eXtensible Markup Language). If you are familiar with these recognized formats, you should notice lots of similarities in UXML. However, the UXML format includes small differences to provide an efficient way to work with Unity.
This section describes the UXML format that Unity supports and provides details on writing, loading, and defining UXML templates. It also includes information on defining new elements, and how to use UQuery.
UXML makes it is easier for less technical users to build a user interface within Unity. In UXML you can:
This leaves developers to do technical tasks, such as importing assets, defining logic, and processing data.
UI Toolkit is extensible. You can define your own user interface components and elements.
Before you can use UXML files to define new elements, you must derive a new class from VisualElement
or one of its subclasses, then implement the appropriate functionality within this new class. Your new class must implement a default constructor.
For example, the following code derives the new StatusBar
class and implements its default constructor:
class StatusBar : VisualElement
{
public StatusBar()
{
m_Status = String.Empty;
}
string m_Status;
public string status { get; set; }
}
In order for UI Toolkit to instantiate a new class when reading a UXML file, you must define a factory for your class. Unless your factory needs to do something special, you can derive the factory from UxmlFactoy<T>
. It’s recommended that you put the factory class within your component class.
For example, the following code demonstrates how to define a factory for the StatusBar
class by deriving its factory from UxmlFactory<T>
. The factory is named UxmlFactory
:
class StatusBar : VisualElement
{
public new class UxmlFactory : UxmlFactory<StatusBar> {}
// ...
}
With this factory defined, you can use the <StatusBar>
element in UXML files.
You can define UXML traits for a new class and set its factory to use these traits.
For example, the following code demonstrates how to define a UXML traits class to initialize the status
property as a property of the StatusBar
class. The status property is initialized from XML data.
class StatusBar : VisualElement
{
public new class UxmlFactory : UxmlFactory<StatusBar, UxmlTraits> {}
public new class UxmlTraits : VisualElement.UxmlTraits
{
UxmlStringAttributeDescription m_Status = new UxmlStringAttributeDescription { name = "status" };
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get { yield break; }
}
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
((StatusBar)ve).status = m_Status.GetValueFromBag(bag, cc);
}
}
// ...
}
The UxmlTraits
serves two purposes:
It is used by the factory to initialize the newly created object.
It is analyzed by the schema generation process to get information about the element. This information is translated into XML schema directives.
The code example above does the following:
m_Status
defines an XML attribute named status
.uxmlChildElementsDescription
returns an empty IEnumerable
which indicates that StatusBar
element has no child.Init()
member reads the value of the status
attribute in a property bag from the XML parser and sets the StatusBar.status
property to this value.UxmlTraits
class inside the StatusBar
class allows the Init()
method to access the private members of StatusBar
.UxmlTraits
class inherits from the base class UxmlTraits
, so it shares the attributes of the base class.Init()
calls base.Init()
to initialize the base class properties.The code example above declares a string attribute with the UxmlStringAttributeDescription
class. UI Toolkit supports the following types of attributes and each links a C# type to an XML type:
Attribute | Attribute value |
---|---|
UxmlStringAttributeDescription |
A string |
UxmlFloatAttributeDescription |
A single precision floating point value in the range of the C# float type. |
UxmlDoubleAttributeDescription |
A double precision floating point value in the range of the C# double type. |
UxmlIntAttributeDescription |
An integer value in the range of the C# int type. |
UxmlLongAttributeDescription |
A long integer value in the range of the C# long type. |
UxmlBoolAttributeDescription |
true or false
|
UxmlColorAttributeDescription |
A string representing a color (#FFFFFF ) |
UxmlEnumAttributeDescription<T> |
A string representing one of the values for the Enum type T . |
In the code example above, the uxmlChildElementsDescription
returns an empty IEnumerable
which indicates that the StatusBar
element does not accept children.
To have an element accept children of any type, you must override the uxmlChildElementsDescription
property. For example, for the StatusBar
element to accept children of any type, the uxmlChildElementsDescription
property must be specified as follows:
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get
{
yield return new UxmlChildElementDescription(typeof(VisualElement));
}
}
Once you have defined a new element in C#, you can start using the element in your UXML files. If your new element is defined in a new namespace, you should define a prefix for the namespace. Namespace prefixes are declared as attributes to the root <UXML>
element and replace the full namespace name when scoping elements.
To define a namespace prefix, add a UxmlNamespacePrefix
attribute to your assembly for each namespace prefix you want to define.
[assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
[assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]
This can be done at the root level (outside any namespace) of any C# file of the assembly.
The schema generation system does the following:
<UXML>
element in newly created UXML filesxsi:schemaLocation
attribute.You should update the UXML schema of your project. Select Assets > Update UXML Schema to ensure that your text editor recognizes the new element.
The defined prefix is available in the newly created UXML by selecting Create > UI Toolkit > Editor Window in the Project/Assets/Editor
folder.
You can customize a UXML name by overriding its IUxmlFactory.uxmlName
and IUXmlFactory.uxmlQualifiedName
properties. Make sure the uxmlName
is unique within your namespace and that the uxmlQualifiedName
is unique in your project.
If both names are not unique, an exception is thrown when you attempt to load your assembly.
The following code example demonstrates how to override and custom the UXML name:
public class FactoryWithCustomName : UxmlFactory<..., ...>
{
public override string uxmlName
{
get { return "UniqueName"; }
}
public override string uxmlQualifiedName
{
get { return uxmlNamespace + "." + uxmlName; }
}
}
By default, the IUxmlFactory
instantiates an element and selects the element using the name of the element.
You can make the selection process consider attribute values on the element by overriding IUXmlFactory.AcceptsAttributeBag
. The factory will then examine the element attributes to decide if it can instantiate an object for the UXML element.
This is useful if, for example, your VisualElement
class is generic. In this case, the class factory for a specialization of your class could examine the value of a XML type
attribute. Depending on the value, instantiation could be accepted or refused. See the implemenatation of PropertyControl<T>
for an example.
In the case where more than one factory can instantiate an element, the first registered factory is selected.
You can change the default value of an attribute declared in a base class by setting its defaultValue
in the derived UxmlTraits
class.
For example, the following code shows how to change the default value of m_TabIndex
:
class MyElementTraits : VisualElement.UxmlTraits
{
public MyElementTraits()
{
m_TabIndex.defaultValue = 0;
}
}
By default, the generated XML schema states that an element can have any attribute.
Values of attributes, other than those declared in the UxmlTraits
class, are not restricted. This is in contrast to XML validators that check that the value of a declared attribute matches its declaration.
Additional attributes are included in the IUxmlAttributes
bag that is passed to the IUxmlFactory.AcceptsAttributBag()
and IUxmlFactory.Init()
functions. It is up to the factory implementation whether to use these additional attributes. The default behavior is to discard additonal attributes.
This means that these additional attributes are not attached to the instantiated VisualElement
and these atttibutes are not queryable with UQuery
.
When defining a new element, you can restrict the accepted attributes to those explicitly declared by setting the UxmlTraits.canHaveAnyAttribute
property to false
in your UxmlTraits
constructor.
Schema definition files specify the attributes and which child elements each UXML element can contain. Use schema definition files as a guide for writing correct documents and to validate your documents.
In the UXML template file, the xsi:noNamespaceSchemaLocation
and xsi:schemaLocation
attributes of the <UXML>
root element specify where the schema definition files are located.
Select Assets > Create > UI Toolkit > Editor Window to automatically update your schema definition with the latest information from the VisualElement
sub-classes used by your project. To force an update of the UXML schema files, select Assets > Update UXML Schema.
Note: Some text editors do not recognize the xsi:noNamespaceSchemaLocation
attribute. If your text editor cannot find the schema definition files, you should also specify the xsi:schemaLocation
attribute.
When you visit any website, it may store or retrieve information on your browser, mostly in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. The information does not usually directly identify you, but it can give you a more personalized web experience. Because we respect your right to privacy, you can choose not to allow some types of cookies. Click on the different category headings to find out more and change our default settings. However, blocking some types of cookies may impact your experience of the site and the services we are able to offer.
More information
These cookies enable the website to provide enhanced functionality and personalisation. They may be set by us or by third party providers whose services we have added to our pages. If you do not allow these cookies then some or all of these services may not function properly.
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance.
These cookies may be set through our site by our advertising partners. They may be used by those companies to build a profile of your interests and show you relevant adverts on other sites. They do not store directly personal information, but are based on uniquely identifying your browser and internet device. If you do not allow these cookies, you will experience less targeted advertising. Some 3rd party video providers do not allow video views without targeting cookies. If you are experiencing difficulty viewing a video, you will need to set your cookie preferences for targeting to yes if you wish to view videos from these providers. Unity does not control this.
These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not then work. These cookies do not store any personally identifiable information.