一个预制体一种资产类型,允许您存储一个 GameObject,包含其组件和属性。预制体充当模板,您可以从中在场景中创建新的对象实例。 更多信息
在 术语表 中查看 是一个预制好的GameObjectUnity 场景中的基本对象,可以表示角色、道具、场景、摄像机、航点等等。GameObject 的功能由附加到它的组件定义。 更多信息
在 术语表 中查看,您可以在一个场景场景包含游戏环境和菜单。将每个独特的场景文件视为一个独特的关卡。在每个场景中,您放置环境、障碍物和装饰,本质上是设计和构建游戏的各个部分。 更多信息
在 术语表 中查看 中多次实例化。预制体对于创建可复用组件很有用。 视觉元素视觉树中的一个节点,它实例化或派生自 C# VisualElement
类。您可以设置外观、定义行为,并将其显示在屏幕上作为 UI 的一部分。 更多信息
在 术语表 中查看 在 UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三种 UI 系统。 更多信息
在 术语表 中查看 工具包中不是 GameObjects,因此预制体不适用。但是,您可以 创建自定义控件 作为可复用的 UI 组件,它封装了具有逻辑的特定元素层次结构。由于 UI 工具包鼓励您将 UI 与游戏或应用程序代码分离,您可以使用 UXML 来定义结构,使用 USS 来定义外观,并使用 C# 来定义自定义控件的逻辑。
例如,假设您想要创建一个纸牌游戏。您想要显示带有不同统计数据的卡片,例如生命值和攻击力。
您可以创建一个名为 CardElement
的自定义控件,它显示角色的图像、生命值和攻击力统计数据,然后在游戏中为每张卡片重复使用此自定义控件。
以下是一般步骤来完成此操作
在 C# 中,声明一个自定义元素类型,名为 CardElement。
在 UXML 中,定义自定义控件的层次结构。您可以使用两种方法。这两种方法都支持在 C# 和父 UXML 中实例化 CardElement
。
定位自定义控件的子元素的引用。
公开属性和方法,并像您对任何 C# 类一样在自定义控件中封装逻辑。
将自定义控件与您的游戏或应用程序代码连接起来。您还可以注册事件回调来实现用户交互。
使用这种方法,您将自定义元素 CardElement 包含在层次结构 UXML 文档中,并直接在其下方声明其子元素,并将层次结构 UXML 文档用作模板。这种方法提供了一个更简单的解决方案,在层次结构 UXML 文档中具有固定的 UI 结构。
以下 C# 和 UXML 示例演示了如何使用 UXML 优先方法来创建可复用的 UI。
创建一个 C# 脚本,它定义 CardElement 自定义控件。自定义控件类将图像和徽章值分配给 CardElement。
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
[UxmlElement]
public partial class CardElement : VisualElement
{
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Use the Init() approach instead of a constructor because
// we don't have children yet.
public void Init(Texture2D image, int health, int attack)
{
portraitImage.style.backgroundImage = image;
attackBadge.text = health;
healthBadge.text = attack;
}
// Custom controls need a default constructor.
public CardElement() {}
}
创建一个 UXML 文档 (CardElement.uxml
),它定义 CardElement 的层次结构。此示例使用 USS 文件来设置 CardElement 的样式。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<CardElement>
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</CardElement>
</ui:UXML>
您可以通过以下方式将自定义控件连接到您的游戏
CardElement.uxml
。您可以在 UI Builder 中 在层次结构 UXML 和此 UXML 文档之间来回导航。CardElement
的 CardElement.uxml
。您必须使用 UQuery 在将 CardElement 添加到场景之前找到它。您在将自定义控件添加到场景后调用 Init()
。
您还可以添加与游戏相关的操作,例如单击事件来与元素进行交互。
在父 UXML 中实例化
以下显示了在 UXML 中实例化的示例
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:Template name="CardElement" src="CardElement.uxml"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
</ui:UXML>
有关如何在您的游戏中呈现 UXML 文档的信息,请参阅 在游戏视图中渲染 UI。
直接在 C# 中实例化
注意:出于学习目的,此页面上的示例代码使用 Resources 文件夹 方法来加载 UXML 文件,这很方便。但是,这种方法不能很好地扩展。建议您在生产项目中使用 其他方法 来加载引用。
以下显示了在 C# 中实例化的示例
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Load the UXML document that defines the hierarchy of CardElement.
// It assumes the UXML file is placed at the "Resources" folder.
VisualTreeAsset template = Resources.Load<VisualTreeAsset>("CardElement");
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
// Instantiate a template container.
var templateContainer = template.Instantiate();
// Find the custom element inside the template container.
var cardElement = templateContainer.Q<CardElement>();
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
// Initialize the card.
cardElement.Init(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
使用这种方法,您只将子元素包含在层次结构 UXML 文档中,并使用 C# 来 将层次结构 UXML 文档加载 到 CardElement 类定义中。这种方法为自定义控件提供了灵活的 UI 结构。例如,您可以根据特定条件加载不同的层次结构 UXML 文档。
以下 C# 和 UXML 示例演示了如何使用元素优先方法来创建可复用的 UI。
创建一个 C# 脚本,它定义 CardElement 自定义控件。除了 定义一个构造函数来将图像和徽章值分配给 CardElement 之外,自定义控件还在其类定义中加载层次结构 UXML 文档。
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
[UxmlElement]
public partial class CardElement : VisualElement
{
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Custom controls need a default constructor. This default constructor
// calls the other constructor in this class.
public CardElement() {}
// Define a constructor that loads the UXML document that defines
// the hierarchy of CardElement and assigns an image and badge values.
public CardElement(Texture2D image, int health, int attack)
{
// It assumes the UXML file is called "CardElement.uxml" and
// is placed at the "Resources" folder.
var asset = Resources.Load<VisualTreeAsset>("CardElement");
asset.CloneTree(this);
portraitImage.style.backgroundImage = image;
attackBadge.text = health.ToString();
healthBadge.text = attack.ToString();
}
}
注意:如果您担心性能问题,请使用延迟初始化来保留字段以缓存引用,并避免过于频繁地重新评估查询。
创建一个 UXML 文档 (CardElement.uxml
),它定义 CardElement 的子元素的层次结构。此示例使用 USS 文件来设置 CardElement 的样式。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</ui:UXML>
您可以通过执行以下操作将自定义控件连接到您的游戏
CardElement.uxml
。在 UI Builder 中,您无法在层次结构 UXML 和此 UXML 文档之间来回导航,因为子元素是从 C# 加载的。CardElement
的 CardElement.uxml
。您在将自定义控件添加到场景之前调用构造函数。
您还可以添加与游戏相关的操作,例如单击事件来与元素进行交互。
在父 UXML 中实例化
以下显示了在 UXML 中实例化的示例
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<CardElement />
<CardElement />
<CardElement />
</ui:UXML>
有关如何在您的游戏中呈现 UXML 文档的信息,请参阅 在游戏视图中渲染 UI。
直接在 C# 中实例化
以下显示了在 C# 中实例化的示例
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
var cardElement = new CardElement(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
随着项目 UI 的越来越复杂,最好将您的逻辑隔离到更高级别的组件中。这使得为游戏的其余部分或应用程序编排 UI 变得更容易。
您可以将本页上的概念应用于逐渐从更小、更通用的组件构建专门的组件。例如,要从主标题屏幕构建用户可以访问“选项”菜单和“关于”部分的主标题屏幕,您可以创建一个名为 TitleScreenManager 的元素,其中包含三个不同的子 UXML 文档。每个文档都定义了自己的元素:标题、选项和关于。