Unity 可扩展标记语言 (UXML) 文件是定义用户界面逻辑结构的文本文件。UXML 格式受到 HTML、XAML 和 XML 的启发。如果您以前使用过这些格式,会发现与 UXML 的相似之处。但是,UXML 格式包含一些小差异,旨在与 Unity 高效融合。
本节介绍 Unity 支持的 UXML 格式,并提供有关编写、加载和定义 UXML 模板的详细信息。还包含有关定义新元素以及如何使用 UQuery 的信息。
UXML 使技术水平较低的用户更容易在 Unity 中构建用户界面。在 UXML 中可以:
因此,开发者可以将精力集中于执行一些技术性工作,例如导入资源、定义逻辑和处理数据。
使用 UI 工具包,您可以定义自己的用户界面组件和元素。
在使用 UXML 文件来定义新元素之前,必须从 VisualElement
或其子类之一派生一个新类,然后在此新类中实现相应功能。新类必须实现默认构造函数。
例如,以下代码派生新的 StatusBar
类并实现其默认构造函数:
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 UxmlFactory<T>
. It’s recommended that you put the factory class within your component class.
例如,以下代码演示了如何通过从 UxmlFactory<T>
派生 StatusBar
类的工厂来为该类定义工厂。该工厂名为 UxmlFactory
:
class StatusBar : VisualElement
{
public new class UxmlFactory : UxmlFactory<StatusBar> {}
// ...
}
定义该工厂后,就可以在 UXML 文件中使用 <StatusBar>
元素。
可为新类定义 UXML 特征,并将其工厂设置为使用这些特征。
例如,以下代码演示了如何定义 UXML 特征类,从而将 status
属性初始化为 StatusBar
类的属性。该 status 属性从 XML 数据初始化。
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);
}
}
// ...
}
UxmlTraits
有两个作用:
以上代码示例执行以下操作:
m_Status
的声明定义一个名为 status
的 XML 属性。uxmlChildElementsDescription
返回空的 IEnumerable
(表明 StatusBar
元素没有子项)。Init()
成员从 XML 解析器读取属性包中的 status
属性值,并将 StatusBar.status
属性设置为此值。UxmlTraits
类置于 StatusBar
类中,让 Init()
方法可以访问 StatusBar
的私有成员。UxmlTraits
类继承自基类 UxmlTraits
,因此其共享基类的属性。Init()
调用 base.Init()
来初始化基类属性。以上代码示例使用 UxmlStringAttributeDescription
类声明了一个字符串属性。UI 工具包支持以下类型的属性,每个属性都将 C# 类型链接到 XML 类型:
属性 | 属性值 |
---|---|
UxmlStringAttributeDescription |
字符串 |
UxmlFloatAttributeDescription |
C# float 类型范围内的单精度浮点值。 |
UxmlDoubleAttributeDescription |
C# double 类型范围内的双精度浮点值。 |
UxmlIntAttributeDescription |
C# int 类型范围内的整数值。 |
UxmlLongAttributeDescription |
C# long 类型范围内的长整数值。 |
UxmlBoolAttributeDescription |
true 或 false
|
UxmlColorAttributeDescription |
表示颜色的字符串 (#FFFFFF ) |
UxmlEnumAttributeDescription<T> |
表示 Enum 类型 T 的值之一的字符串。 |
在以上示例中,uxmlChildElementsDescription
返回一个空的 IEnumerable
,表示 StatusBar
元素不接受子项。
要让元素接受任何类型的子项,必须覆盖 uxmlChildElementsDescription
属性。例如,为了让 StatusBar
元素接受任何类型的子项,必须按如下方式指定 uxmlChildElementsDescription
属性:
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get
{
yield return new UxmlChildElementDescription(typeof(VisualElement));
}
}
一旦在 C# 中定义了新元素,就可以开始在 UXML 文件中使用该元素。如果在新命名空间中定义新元素,应该为此命名空间定义一个前缀。命名空间前缀声明为根元素 <UXML>
的属性,并在限定元素范围时替换命名空间的全名。
要定义命名空间前缀,请将 UxmlNamespacePrefix
属性添加到要定义的每个命名空间前缀的程序集。
[assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
[assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]
此操作可以在程序集的任何 C# 文件的根级别(在任何命名空间之外)完成。
架构生成系统会执行以下操作:
<UXML>
元素的属性。xsi:schemaLocation
属性中。应该更新项目的 UXML 架构。请选择 Assets > Update UXML Schema 以确保文本编辑器识别新元素。
通过在 Project/Assets/Editor
文件夹中选择 Create > UI Toolkit > Editor Window,可以在新创建的 UXML 中使用定义的前缀。
若要自定义 UXML 名称,可覆盖其 IUxmlFactory.uxmlName
和 IUXmlFactory.uxmlQualifiedName
属性。确保 uxmlName
在命名空间内具有唯一性且 uxmlQualifiedName
在项目中具有唯一性。
如果两个名称不唯一,则在尝试加载程序集时将抛出异常。
以下代码示例演示了如何覆盖和自定义 UXML 名称:
public class FactoryWithCustomName : UxmlFactory<..., ...>
{
public override string uxmlName
{
get { return "UniqueName"; }
}
public override string uxmlQualifiedName
{
get { return uxmlNamespace + "." + uxmlName; }
}
}
默认情况下,IUxmlFactory
会实例化一个元素并使用该元素的名称来选择该元素。
可以通过覆盖 IUXmlFactory.AcceptsAttributeBag
使选择过程考虑元素上的属性值。然后,工厂将检查元素属性以决定是否可以为 UXML 元素实例化对象。
例如,如果 VisualElement
类为泛类,这将很有用。在这种情况下,用于类特化的类工厂可以检查 XML type
属性的值。根据值的不同,可以接受或拒绝实例化。例如,请参阅 PropertyControl<T>
的实现。
如果有多个工厂可以实例化元素,则会选择第一个已注册的工厂。
若要更改基类中声明的属性的默认值,可在派生的 UxmlTraits
类中设置该属性的 defaultValue
。
例如,以下代码演示了如何更改 m_TabIndex
的默认值:
class MyElementTraits : VisualElement.UxmlTraits
{
public MyElementTraits()
{
m_TabIndex.defaultValue = 0;
}
}
默认情况下,生成的 XML 架构会声明元素可以具有任何属性。
属性值(在 UxmlTraits
类中声明的属性除外)不受限制。这一点与 XML 验证器相反,后者会检查已声明属性的值是否与其声明匹配。
其他属性包含在传递到 IUxmlFactory.AcceptsAttributBag()
和 IUxmlFactory.Init()
函数的 IUxmlAttributes
包中。是否使用这些附加属性取决于工厂的实现。默认行为是丢弃附加属性。
这意味着这些附加属性不会附加到实例化的 VisualElement
,并且不能使用 UQuery
来查询这些属性。
定义新元素时,可以通过在 UxmlTraits
构造函数中将 UxmlTraits.canHaveAnyAttribute
属性设置为 false
,将接受的属性限制为显式声明的属性。
架构定义文件用于指定属性以及每个 UXML 元素可以包含的子元素。请将架构定义文件用作编写正确文档和验证文档的指南。
在 UXML 模板文件中,<UXML>
根元素的 xsi:noNamespaceSchemaLocation
和 xsi:schemaLocation
属性指定了架构定义文件所在位置。
选择 Assets > Create > UI Toolkit > Editor Window,即可使用从项目所用的 VisualElement
子类中收集的最新信息来自动更新架构定义。要强制更新 UXML 架构文件,请选择 Assets > Update UXML Schema。
注意:某些文本编辑器无法识别 xsi:noNamespaceSchemaLocation
属性。如果文本编辑器找不到架构定义文件,您还应指定 xsi:schemaLocation
属性。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.