Unity3D :编写 UXML 模板
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
编写 UXML 模板
UXML 模板是使用 XML 标记编写的文本文件,用于定义用户界面的逻辑结构。 以下代码示例演示了如何定义一个提示用户做出选择的简单面板:
<?xml version="1.0" encoding="utf-8"?>
<UXML
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="UnityEngine.UIElements"
xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
<Label text="Select something to remove from your suitcase:"/>
<Box>
<Toggle name="boots" label="Boots" value="false" />
<Toggle name="helmet" label="Helmet" value="false" />
<Toggle name="cloak" label="Cloak of invisibility" value="false"/>
</Box>
<Box>
<Button name="cancel" text="Cancel" />
<Button name="ok" text="OK" />
</Box>
</UXML>
文件的第一行是 XML 声明。 此声明为可选项。 如果包含此声明,它必须在第一行,并且在它之前不能出现其他内容或空格。 属性是必需属性。 属性是可选属性。 如果包含 ,它必须声明文件的字符编码。versionencodingencoding
下一行定义文档根 。 元素包含命名空间前缀定义的属性和架构定义文件的位置。 可以按任意顺序指定这些属性。<UXML><UXML>
在 UI 工具包中,每个元素都在 或 命名空间中定义:UnityEngine.UIElementsUnityEditor.UIElements
UnityEngine.UIElements
命名空间包含被定义为 Unity Runtime 一部分的元素。UnityEditor.UIElements
命名空间包含 Unity Editor 中可用的元素。 要完整指定一个元素,必须在其前面添加其命名空间。
例如,如果要在 UXML 模板中使用 元素,则必须指定 。Button<UnityEngine.UIElements:Button />
要方便指定命名空间,可以定义命名空间前缀。 例如, 将 前缀定义为 。 定义命名空间前缀之后,可以将其用于指定命名空间。 例如, 等同于 xmlns:engine="UnityEngine.UIElements"engineUnityEngine.UIElements<engine:Button /><UnityEngine.UIElements:Button />
还可以通过排除前缀来定义默认命名空间。 例如, 将 定义为默认命名空间。 这意味着指定 等同于 xmlns="UnityEngine.UIElements"UnityEngine.UIElements<Button /><UnityEngine.UIElements:Button />
如果是自行定义元素,这些元素可能在其自身的命名空间中定义。 如果要在 UXML 模板中使用这些元素,则必须在 标签中包含命名空间定义和架构文件位置以及 Unity 命名空间。<UXML>
通过选择 Asset > Create > UI Toolkit > Editor Window 来新建 UXML 模板资源时,编辑器自动为您定义命名空间。
UI 的定义在 根中。 UI 定义是一系列嵌套的 XML 元素,每个元素代表一个 。<UXML>VisualElement
元素名称对应于要实例化的元素的 C# 类名。 大多数元素都有属性,且属性的值映射到 C# 中相应的类属性。 每个元素都继承其父类类型的属性,并可在父类类型的基础上添加自己的属性集。 作为所有元素的基类,为所有元素提供以下属性:VisualElement
name
:元素的标识符。 名称应具有唯一性。picking-mode
:设置为 (响应鼠标事件)或 (忽略鼠标事件)。PositionIgnore
focus-index
:(已弃用)使用 和 。tabIndexfocusable
tabindex
:一个整数,定义当前元素的 Tab 键移动位置。focusable
:一个布尔值,指示是否可聚焦该元素。class
:用于表征元素的标识符的空格分隔列表。 使用类为元素指定视觉样式。 还可以使用类在 UQuery 中选择一组元素。tooltip
:鼠标悬停在元素上方时显示为工具提示的字符串。view-data-key
:一个字符串,可定义用于元素序列化的键。
UXML 模板示例未定义用户界面的视觉要素。 建议您使用单独的 USS 文件来定义用于绘制 UI 的样式信息,例如尺寸、字体和颜色(请参阅样式和 Unity 样式表)。
向 UXML 添加样式
要引用样式表文件,UXML 文件可以在任何元素声明下使用 元素。<Style>
例如,如果您在同一文件夹中有一个 UXML 文件以及一个名为 “styles.uss” 的 USS 文件:
<engine:UXML ...>
<engine:VisualElement class="root">
<Style src="styles.uss" />
</engine:VisualElement>
</engine:UXML>
# root {
width: 200px;
height: 200px;
background-color: red;
}
注意: Unity 不支持根 元素下的 元素。<UXML><Style>
还可以直接将内联样式声明为 UXML 元素的属性:
<engine:UXML ...>
<engine:VisualElement style="width: 200px; height: 200px; background-color: red;" />
</engine:UXML>
重用 UXML 文件
可通过在 UXML 文件中定义组件的方式来创建组件, 并使用另一个 UXML 文件中的 和 元素将组件导入。<Template><Instance>
在设计大型用户界面时,可以创建一些用于定义 UI 组成部分的模板 UXML 文件。
可能会在许多地方使用相同的 UI 定义。 例如,假设有一个包含图像、名称和标签的纵向 UI 元素。 可以创建一个 UXML 模板文件以便在其他 UXML 文件中重用此纵向 UI 元素。
例如,假设在 文件中有一个 Portrait 组件:Assets/Portrait.uxml
<engine:UXML ...>
<engine:VisualElement class="portrait">
<engine:Image name="portaitImage" style="--unity-image: url(\"a.png\")"/>
<engine:Label name="nameLabel" text="Name"/>
<engine:Label name="levelLabel" text="42"/>
</engine:VisualElement>
</engine:UXML>
可以将 Portrait 组件嵌入到其他 UXML 模板中,如下所示:
<engine:UXML ...>
<engine:Template src="/Assets/Portrait.uxml" name="Portrait"/>
<engine:VisualElement name="players">
<engine:Instance template="Portrait" name="player1"/>
<engine:Instance template="Portrait" name="player2"/>
</engine:VisualElement>
</engine:UXML>
覆盖 UXML 属性
创建 UXML 模板的实例时,您可以覆盖其元素的默认属性值。 属性覆盖允许多次实例化同一模板,每个实例使用不同的值。
要覆盖属性,您必须指定:
- 要覆盖其属性的元素的
element-name 属性
- 要覆盖的属性的名称。
- 新属性值
在下面的示例中,
player-name-label
是元素的 属性。element-name
text
是要覆盖的属性。Alice
是新属性值
<AttributeOverrides element-name="player-name-label" text="Alice" />
属性覆盖会影响整个实例,因此如果实例有两个名为 的元素,并且都具有 属性,则覆盖会对二者都有影响。player-name-labeltext
属性覆盖示例
假设您正在制作一款游戏,并且希望为每个玩家显示相同的信息集。 您可以创建一个可重用的模板,并使用属性覆盖来创建特定于玩家的实例。
例如,如果您创建以下模板:
<UXML xmlns="UnityEngine.UIElements">
<Label name="player-name-label" text="default name" />
<Label name="player-score-label" text="default score" />
</UXML>
您可以从另一个 UXML 文件中实例化它并覆盖其属性以显示每个玩家的姓名和分数:
<UXML xmlns="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<Template src="MyTemplate.uxml" name="MyTemplate" />
<Instance name="player1" template="MyTemplate">
<AttributeOverrides element-name="player-name-label" text="Alice" />
<AttributeOverrides element-name="player-score-label" text="2" />
</Instance>
<Instance name="player2" template="MyTemplate">
<AttributeOverrides element-name="player-name-label" text="Bob" />
<AttributeOverrides element-name="player-score-label" text="1" />
</Instance>
</UXML>
覆盖多个属性
您可以为每个覆盖指定多个属性。 例如,以下语法查找名为 的实例中的任何元素,并且player-name-label
- 用新值 覆盖其 属性的默认值。
Alicetext
- 用新值 覆盖其 属性的默认值。
Tooltip 1tooltip
<AttributeOverrides element-name="player-name-label" text="Alice" tooltip="Tooltip 1" />
嵌套属性覆盖
属性覆盖通过元素层级结构中的嵌套模板传播。 例如,如果模板 A 实例化模板 B,而模板 B 实例化模板 C,则模板 A 和模板 B 都可以覆盖模板 C 中的属性。
当您覆盖嵌套模板中的属性时,最深的覆盖优先。 因此,在上面的示例中,如果模板 A 和模板 B 都覆盖了模板 C 的相同属性,则模板 B 中的覆盖决定了呈现的 UI 中实际出现的内容。
限制
- 属性覆盖根据您指定的元素名称查找匹配的属性。 它们不使用 USS 选择器或者 UQUery 来匹配元素。
- 属性覆盖与数据绑定无关,尽管您可以覆盖元素的 属性。
binding-path
- 您不能覆盖元素的 或 属性。
namestyle
从UXML引用其他文件
UXML 文件可以通过元素引用其他 UXML 文件和 USS 文件。
<Template>
和 元素都接受“src”属性或“path”属性。<Style>
src
属性允许相对路径,在导入时(例如,文件丢失时)提供错误消息,并确保 Unity 在播放器构建中正确包含 UXML 文件引用的资源。
path
属性允许使用 Unity 资源机制,但在导入时不提供错误报告,并且不允许使用相对路径。
src
属性
src
属性要求文件路径相对于项目根目录或包含 UXML 文件的文件夹。 必须包含文件扩展名。 在以下示例中,UXML 文件位于 Assets\Editor\UXML 中,USS 文件位于 Assets\Editor\USS 中。
- 根据 UXML 文件的位置,使用以下示例路径之一: 或
src="../USS/styles.uss"src="template.uxml"
- 根据项目的位置,使用以下示例之一表示绝对路径: 或 。
src="/Assets/Editor/USS/styles.uss"src="project:/Assets/Editor/UXML/template.uxml"
path
属性
path
属性接受位于 Resources 文件夹或 Editor Default Resources 文件夹中的文件,并遵循以下规则:
- 如果文件位于 Resources 文件夹中,不得包含文件扩展名。 例如,为位于 Assets/Resources/template.uxml 的文件编写 。
path="template"
- 如果文件位于 Editor Default Resources 文件夹中,必须包含文件扩展名。 例如,为位于 Assets/Editor Default Resources/template.uxml 的文件编写 。
path="template.uxml"
由3D建模学习工作室整理翻译,转载请注明出处!