关于编辑器:Unity3D-创建您的第一个运行时-UI

11次阅读

共计 18624 个字符,预计需要花费 47 分钟才能阅读完成。

举荐:将 NSDT 场景编辑器退出你的 3D 工具链 https://studio.nsdt.cloud/
3D 工具集:NSDT 简石数字孪生创立

您的第一个运行时 UI 本页将领导您实现应用 UI 工具包设置简略字符抉择屏幕的步骤。它涵盖了 UI 元素和模板的创立、场景设置以及如何将脚本逻辑连贯到 UI。本指南不会介绍通过 USS 设置款式,并且仅应用默认款式和主题。您能够在本页底部此处找到本指南的最终源代码。主题:UI 生成器、列表视图、标签、面板设置、UIDocument、抉择解决

本指南将领导您实现以下步骤:创立主 UI 视图设置场景创立要显示的示例数据为主视图创立控制器创立列表条目 UI 模板为列表条目创立控制器对用户抉择做出反馈创立主 UI 视图最终的 UI 屏幕由两个独自的 UI 模板(UXML)组成。主视图模板蕴含蕴含字符名称的列表、用于显示所选字符详细信息的较小面板以及一个按钮。在本节中,您将应用 UI 生成器设置此模板。留神:如果您相熟 UI 生成器并心愿跳过此步骤,则能够从此页面底部复制主视图的 UXML 代码,并将其间接粘贴到新文件中。将其另存为 Assets/UI/MainView.uxml。

主视图的 UI 布局设置通过菜单“UI Toolkit> UI Builder”关上“UI 生成器”窗口 >“UI 生成器”窗口。应用视口左上角的文件菜单创立新的 UXML 文档。

UI 生成器文件菜单开发游戏 UI 时,请始终确保抉择 UI 生成器视口右上角的。编辑器和运行时主题之间的默认字体大小和色彩不同,这会影响布局。Unity Default Runtime Theme

通过从库中拖动来创立新元素在层次结构中抉择新的 UXML 文件,而后启用匹配游戏视图复选框。您可能须要将 Unity 编辑器设置为横向分辨率(如果尚未设置)。

启用较量游戏视图当初是时候创立 UI 元素了!通过将新的可视元素从库拖到层次结构中来创立新的可视元素。

通过从库中拖动来创立新元素新元素须要笼罩整个屏幕,因而须要将属性设置为 1。从层次结构中抉择元素,而后在右侧的“查看器”面板中找到标记为 Flex 的折叠页。将“增长”的值从 0 更改为 1。flex-grow

设置 Flex 属性若要将此可视元素的所有子项居中置于屏幕两头,请更改可视元素的“对齐”属性。您须要将“对齐我的项目”和“内容对齐”都设置为居中。

居中儿童最初,您能够在“背景 > 色彩”下抉择一种背景色彩。此步骤是可选的。此示例用作色彩。#732526

根元素背景色接下来,在现有可视元素下创立一个新的可视元素。这将成为 UI 左侧和右侧局部的父容器。

增加子可视元素将此新元素的属性设置为(默认为列)。您还须要将固定高度设置为 350 像素。flex-directionrow

核心容器属性这就是以后 UI 的外观。请留神,您的屏幕可能看起来会有所不同,具体取决于游戏视图的分辨率和纵横比。

外部有空元素的背景容器若要为字符名称创立列表,请从库中抉择一个 ListView 控件,并将其作为子项增加到刚创立的可视元素下。抉择元素并在查看器中为其指定名称。这是必须的,以便您稍后能够通过控制器脚本拜访此列表。CharacterList

外部有空元素的背景容器将列表设置为固定宽度为 230 像素。还要在右侧给它一个 6 px 宽的边距,以便与要创立的下一个元素放弃肯定间隔。

字符列表的大小和边距折叠您还能够为列表指定背景色彩并设置圆角边框。本指南用于背景和边框色彩,边框宽为 4px,半径为 15px。此步骤是可选的。#6E3925#311A11

款式字符列表在与 雷同的父级下增加新的可视元素。这将蕴含角色详细信息面板和按钮。在“对齐”折叠式下,将“我的项目对齐”和“内容对齐”的设置更改为。CharacterListflex-endspace-between

证实内容属性的合理性将新的可视元素增加到此新容器。这将成为角色详细信息面板。当用户从左侧列表中抉择一个角色时,它将显示该角色的肖像、名称和类。为元素设置 276 像素的固定宽度,并将“对齐我的项目”和“内容对齐”切换为居中。还要为元素增加一个 8 像素宽的填充,以便子项与容器边界放弃最小间隔。

字符详细信息容器的属性您能够通过将背景色彩设置为 4px 宽边框和 15px 半径的边框色彩来设置面板款式。此步骤是可选的。#AA5939#311A11 您的 UI 布局当初应相似于下图。

空字符详细信息面板接下来,您将各个 Ui 控件增加到字符详细信息中。首先是人物肖像。它由两个元素组成 – 背景中的帧和前景中的图像。首先将新的可视元素增加到背景帧的字符详细信息容器中。为其调配 120×120 像素的固定大小和 4 像素的填充,以便蕴含的图像不会间接接触边框。您能够应用 2px 宽、半径为 15px 的边框(色彩为 和背景色)来设置元素款式。随便利用您本人的色彩和款式。#311A11#FF8554

人物肖像的背景框架对于理论图像,将新的可视元素作为子元素增加到刚创立的框架中。为其命名,以便当前能够在控制器脚本中拜访它。CharacterPortrait 将“Flex > Grow”设置为 1,以便图像利用所有可用空间。此外,请确保将“背景 > 缩放模式”下的缩放模式更改为,以便能够放大或放大图像以匹配元素大小,同时放弃正确的纵横比。scale-to-fit

纵向图像的可视元素接下来,将两个标签控件增加到字符详细信息容器,稍后将应用这些控件显示所选字符的名称和类。将它们命名为 和。CharacterNameCharacterClass

为名称和类增加标签若要使字符的名称比类更突出,请将标签的字体大小更改为 18,并将款式设置为粗体。

更改字体设置您的 UI 屏幕当初应相似于下图。

实现的角色详细信息面板最初,将按钮控件增加到右侧 UI 容器。稍后,您将在控制器脚本中拜访此按钮,并在抉择或勾销抉择字符时启用或禁用它。命名按钮并为其指定 150px 的固定宽度。还应将按钮的标签文本设置为。SelectCharButtonSelect Character

用于字符抉择的“增加”按钮要设置按钮款式,请将背景色设置为,并将 2px 边框设置为色彩为。此步骤是可选的。#FF8554#311A11 实现的主视图应相似于下图。

最终主视图布局将 UXML 模板另存为 Assets/UI/MainView.uxml。您还能够在此处的页面底部找到此模板的最终 UXML 代码。设置场景在本节中,你将理解如何在运行时在游戏中加载和显示你在上一节中创立的 UI 模板。要开始,您须要创立一个面板设置资产。此资产将定义屏幕的设置,例如缩放模式和渲染程序。它还将确定 UI 在 UI 工具包调试器中显示的名称。

创立新的面板设置资源通过在我的项目视图中单击鼠标右键来创立新的。抉择创立 > UI 工具包 > 面板设置资产。将新创建的文件命名为。对于本指南,您能够将所有设置保留为其默认值。Panel Settings AssetGameUI_Panel

无需更改默认面板设置要显示上一节中的主视图 UI 模板,您须要在场景中创立新的游戏对象。将 UIDocument 组件附加到它。在 Unity 中进入播放模式时,将主动加载调配的内容。A 是一个 UXML 模板。将面板设置和新面板设置都调配给组件。UIDocumentVisualTreeAssetVisualTreeAssetMainView.uxmlGameUI_Panel

UI 文档组件留神:如果未将资源分配给 UI 文档组件,它将主动搜寻我的项目并应用主动找到的第一个面板设置资源。重命名或挪动资产时请记住这一点。PanelSettings 当初,您能够在 Unity 编辑器中进入运行模式,并在游戏视图中查看您的 UI。

运行时显示的 UI 注:如果场景中有多个 UI 文档,则能够将同一面板设置资源分配给所有文档。这将导致所有 UI 出现在同一面板上,从而优化性能。创立要显示的示例数据在本节中,你将创立一些示例数据,这些数据将用于用数据填充 UI 中的字符列表。对于字符列表,您须要一个简略的类,其中蕴含角色名称、类和肖像图像。创立新的 ScriptableObject 脚本 Assets/Scripts/CharacterData.cs 并将以下代码粘贴到文件中:using UnityEngine;

public enum ECharacterClass
{

Knight, Ranger, Wizard

}

[CreateAssetMenu]
public class CharacterData : ScriptableObject
{

public string m_CharacterName;
public ECharacterClass m_Class;
public Sprite m_PortraitImage;

}
该属性将主动向“创立”菜单增加一个条目。右键单击“我的项目”视图中的文件夹以创立新的脚本化对象的实例。[CreateAssetMenu]

新建“创立”菜单项当初,您须要创立一些实例并用随机数据填充它们。将它们全副放在资源 / 字符文件夹中。稍后您将编写一个脚本,该脚本会主动解析并加载此文件夹中的所有字符数据。CharacterData

创立一些示例字符创立列表条目 UI 模板在本节中,您将为列表中的各个条目创立 UI 模板。在运行时,控制器脚本将为每个字符创立此 UI 的实例,并将其增加到列表中。字符列表条目标 UI 由黑白背景框架和字符名称组成。

显示字符名称的列表条目留神:如果要跳过此步骤,能够从此页面底部复制列表条目标 UXML 代码,并将其间接粘贴到新文件中。将其另存为 Assets/UI/ListEntry.uxml。通过菜单“UI Toolkit> UI Builder”关上“UI 生成器”窗口 >“UI 生成器”窗口。通过抉择“新建文件”> 创立新的 UXML 模板。

在 UI 生成器中创立新的 UXML 模板为背景增加一个视觉元素,并将固定高度设置为 41px。因为条目内的文本应左对齐并搁置在元素的两头,因而请关上“对齐”折叠页并将“我的项目左对齐”和“内容对齐”设置为居中。还要设置 10px 的右边距,以使标签与框架左边框的间隔最小。对于款式,您能够应用背景色并增加 2px 宽的边框,半径为 15px,色彩为 . 此步骤是可选的,您能够利用本人的色彩和款式。#AA5939#311A11

背景视觉元素将标签作为子项增加到现有可视元素并命名,以便稍后能够在控制器脚本中拜访它。将“字体款式”设置为粗体,将“字体大小”设置为 18。CharacterName

为角色名称增加标签将 UXML 模板另存为 Assets/UI/ListEntry.uxml。您还能够在此处的页面底部找到此模板的最终 UXML 代码。为列表条目创立控制器在本节中,您将为列表条目创立控制器脚本。该脚本的目标是在列表条目标 UI 中显示字符实例的数据。它须要拜访字符名称的标签,并将其设置为显示给定字符实例的名称。创立一个新脚本 Assets/Scripts/UI/CharacterListEntryController.cs 并将以下代码粘贴到其中:using UnityEngine.UIElements;

public class CharacterListEntryController
{

Label m_NameLabel;

public void SetVisualElement(VisualElement visualElement)
{m_NameLabel = visualElement.Q<Label>("CharacterName");
}

public void SetCharacterData(CharacterData characterData)
{m_NameLabel.text = characterData.m_CharacterName;}

}
此类中有两个函数,它们都是函数。SetSetVisualElement(VisualElement visualElement) 此函数将接管一个可视元素,该元素是您在上一节中创立的 UI 模板的实例。主视图控制器将创立此实例。此函数的目标是检索对 UI 元素内字符名称标签的援用。ListEntrySetCharacterData(CharacterData characterData) 此函数接管此列表元素应显示其名称的字符。因为 中的元素列表是池化和重用的,因而必须有一个函数来更改要显示的角色的数据。ListViewSet 请留神,该类不是 . 因为 UI 工具包中的可视元素不是游戏对象,因而无奈将组件附加到它们。相同,此类将附加到下一节中的属性。CharacterListEntryMonoBehaviouruserData 为主视图创立控制器在本节中,您将为主视图中的字符列表创立一个控制器脚本,以及一个实例化并将其调配给可视化树的 MonoBehavior 脚本。首先,在 Assets/Scripts/UI/CharacterListController 下创立一个新脚本.cs 并将以下代码粘贴到其中。using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

public class CharacterListController
{

public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{}

}
稍后将填充该办法,但当初增加空办法很重要,以便能够在下一节中调用它。InitializeCharacterList() 将控制器脚本附加到主视图就像 一样,the 不是,须要以不同的形式附加到可视化树。您须要创立一个 MonoBehavior 脚本,该脚本能够附加到与 雷同的游戏对象。它将实例化并将其附加到可视化树。CharacterListEntryControllerCharacterListControllerMonoBehaviourUIDocumentCharacterListController 创立一个新脚本 Assets/Scripts/UI/MainView.cs 并将以下代码粘贴到其中:using UnityEngine;
using UnityEngine.UIElements;

public class MainView : MonoBehaviour
{

[SerializeField]
VisualTreeAsset m_ListEntryTemplate;

void OnEnable()
{
    // The UXML is already instantiated by the UIDocument component
    var uiDocument = GetComponent<UIDocument>();

    // Initialize the character list controller
    var characterListController = new CharacterListController();
    characterListController.InitializeCharacterList(uiDocument.rootVisualElement, m_ListEntryTemplate);
}

}
进入 Unity 编辑器,将脚本附加到 所在的同一游戏对象。将 调配给“列表条目模板”属性。UIDocumentListEntry.uxml

增加主视图脚本并调配援用脚本组件无需实例化 MainView UXML,因为这是在同一游戏对象的组件中主动实现的。该脚本拜访 UIDocument 组件以获取已实例化的可视化树的援用。而后,它会创立可视化树的根元素和用于各个列表元素的 UXML 模板的 和 的实例。UIDocumentMainViewCharacterListController 留神:从新加载 UI 时,蕴含该组件的同一游戏对象上的配套 MonoBehavior 组件将在从新加载之前被禁用,而后在从新加载后从新启用。因而,最好将与 UI 交互的代码搁置在这些 MonoBehavior 的 and 办法中。UIDocumentOnEnableOnDisable 枚举所有字符数据实例应增加到控制器脚本的第一个性能是枚举之前创立的所有字符数据实例的函数。这些将用于填写列表。将上面的代码复制到类中。CharacterListControllerList<CharacterData> m_AllCharacters;

void EnumerateAllCharacters()
{

m_AllCharacters = new List<CharacterData>();
m_AllCharacters.AddRange(Resources.LoadAll<CharacterData>("Characters"));

}
留神:此代码假设您在“资源 / 字符”文件夹中创立了字符实例。如果将字符放在其余文件夹中,则可能须要相应地调整文件夹名称。当初,您须要在初始化期间调用该办法。将对其的调用增加到办法的顶部:EnumerateAllCharacterInitializeCharacterListpublic void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{

EnumerateAllCharacters();

}
获取对 UI 元素的援用在本节中,您将填写该办法的内容。此办法须要做的第一件事是获取对它拜访以显示信息所需的所有单个 UI 控件的援用。应用 UQuery 系列 API 按名称、USS 类、类型或这些控件的组合检索各个 UI 控件。InitializeCharacterList 应用以下代码扩大类中的代码:CharacterListController// UXML template for list entries
VisualTreeAsset m_ListEntryTemplate;

// UI element references
ListView m_CharacterList;
Label m_CharClassLabel;
Label m_CharNameLabel;
VisualElement m_CharPortrait;
Button m_SelectCharButton;

public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{

EnumerateAllCharacters();

// Store a reference to the template for the list entries
m_ListEntryTemplate = listElementTemplate;

// Store a reference to the character list element
m_CharacterList = root.Q<ListView>("CharacterList");

// Store references to the selected character info elements
m_CharClassLabel = root.Q<Label>("CharacterClass");
m_CharNameLabel = root.Q<Label>("CharacterName");
m_CharPortrait = root.Q<VisualElement>("CharacterPortrait");

// Store a reference to the select button
m_SelectCharButton = root.Q<Button>("SelectCharButton");

}
用条目填充列表接下来,您须要用之前枚举和加载的字符填充屏幕上的列表。为此,您须要在类中创立一个新办法。FillCharacterListCharacterListController 用元素填充列表视图须要 4 个步骤:创立函数 makeItem 创立函数 bindItem 设置我的项目高度设置我的项目源 makeItem 回调函数的目标是创立一个小的可视化树,该树示意单个列表项的 UI,并返回此树的根可视元素。在这种状况下,回调须要实例化您为列表条目创立的 UXML 模板。它还须要创立控制器脚本的实例,该实例负责应用来自 .makeItemCharacterListEntryControllerCharacterData 在类内创立一个办法并粘贴上面的代码。FillCharacterListvoid FillCharacterList()
{

// Set up a make item function for a list entry
m_CharacterList.makeItem = () =>
{
    // Instantiate the UXML template for the entry
    var newListEntry = m_ListEntryTemplate.Instantiate();

    // Instantiate a controller for the data
    var newListEntryLogic = new CharacterListEntryController();

    // Assign the controller script to the visual element
    newListEntry.userData = newListEntryLogic;

    // Initialize the controller script
    newListEntryLogic.SetVisualElement(newListEntry);

    // Return the root of the instantiated visual tree
    return newListEntry;
};

}
作为回调的一部分,将控制器脚本存储在实例化可视元素的属性中。这容许您稍后拜访脚本并为列表元素调配不同的字符。makeItemuserData// Assign the controller script to the visual element
newListEntry.userData = newListEntryLogic;
作为内存和性能优化,重用列表元素,而不是为列表中的每个条目实例化一个元素。它只创立足够的视觉元素来填充可见区域,而后在滚动列表时会集并重复使用它们。ListView 出于这个起因,你须要提供一个 bindItem 回调,它将你的一个实例(在本例中)绑定到一个独自的列表元素。CharacterData 通过在底部增加上面的代码来扩大该办法。FillCharacterList// Set up bind function for a specific list entry
m_CharacterList.bindItem = (item, index) =>
{

(item.userData as CharacterListEntryController).SetCharacterData(m_AllCharacters[index]);

};
回调接管对列表条目标可视化树的根可视元素的援用,以及数据的索引。因为您在可视元素的属性中存储了对 的援用,因而代码能够拜访它并间接设置 .bindItemCharacterListEntryControlleruserDataCharacterData 最初,您须要设置元素的项高度,并为列表提供对数据源的援用。这通知列表它蕴含多少元素。通过在底部增加上面的代码来扩大该办法。FillCharacterList// Set a fixed item height
m_CharacterList.fixedItemHeight = 45;

// Set the actual item’s source list/array
m_CharacterList.itemsSource = m_AllCharacters;
最初,您须要在初始化完结时调用该办法。将调用增加到办法底部,如下所示:FillCharacterListInitializeCharacterListFillCharacterList();
如果您当初进入播放模式,角色列表将填满您创立的角色的名称。

字符列表不再为空您能够在本指南底部找到脚本的最终代码,此处 CharacterListController 对用户抉择做出反馈当用户抉择角色时,角色的详细信息 – 即肖像,全名和类别 – 须要显示在屏幕右侧的角色详细信息局部中。此外,抉择字符时,须要启用抉择按钮。如果未抉择任何字符,该按钮应再次禁用。请留神,您曾经能够单击并抉择列表中的字符。用于抉择和突出显示的性能是 ListView 控件的一部分。您只须要增加一个回调函数,以便在用户更改列表中的抉择时做出反馈。该控件蕴含用于此目标的事件:ListViewonSelectionChange 将以下代码增加到办法的底部:InitializeCharacterList// Register to get a callback when an item is selected
m_CharacterList.onSelectionChange += OnCharacterSelected;
当初,您须要实现在下面的代码中设置的回调函数。此函数将接管列表中所有选定我的项目的列表。然而,因为列表仅容许抉择单个项,因而能够间接通过列表的 selectedItem 属性拜访所选项。OnCharacterSelected 将以下代码复制到您的类中:void OnCharacterSelected(IEnumerable<object> selectedItems)
{

// Get the currently selected item directly from the ListView
var selectedCharacter = m_CharacterList.selectedItem as CharacterData;

}
该属性可能返回 null。如果未抉择任何内容,或者用户按下该键勾销抉择所有内容,则会呈现这种状况。这个案子须要先解决。selectedItemESC 扩大办法,如下所示:OnCharacterSelectedvoid OnCharacterSelected(IEnumerable<object> selectedItems)
{

// Get the currently selected item directly from the ListView
var selectedCharacter = m_CharacterList.selectedItem as CharacterData;

// Handle none-selection (Escape to deselect everything)
if (selectedCharacter == null)
{
    // Clear
    m_CharClassLabel.text = "";
    m_CharNameLabel.text = "";
    m_CharPortrait.style.backgroundImage = null;

    // Disable the select button
    m_SelectCharButton.SetEnabled(false);

    return;
}

}
如果抉择无效,则须要在 UI 中显示角色的详细信息。能够通过在类的办法中检索到的援用来拜访标签和纵向图像视觉元素。InitializeCharacterList 将上面的代码复制到办法中:OnCharacterSelected// Fill in character details
m_CharClassLabel.text = selectedCharacter.m_Class.ToString();
m_CharNameLabel.text = selectedCharacter.m_CharacterName;
m_CharPortrait.style.backgroundImage = new StyleBackground(selectedCharacter.m_PortraitImage);

// Enable the select button
m_SelectCharButton.SetEnabled(true);
您当初能够进入播放模式并查看您的角色抉择列表。按键勾销抉择字符。Escape

最终运行时 UI 最终脚本您能够在上面找到本指南中创立的所有文件的残缺源代码。MainView.uxml<ui:UXML xmlns:ui=”UnityEngine.UIElements” xmlns:uie=”UnityEditor.UIElements” editor-extension-mode=”False”>

<ui:VisualElement style="flex-grow: 1; align-items: center; justify-content: center; background-color: rgb(115, 37, 38);">
    <ui:VisualElement style="flex-direction: row; height: 350px;">
        <ui:ListView focusable="true" name="CharacterList" style="width: 230px; border-left-color: rgb(49, 26, 17); border-right-color: rgb(49, 26, 17); border-top-color: rgb(49, 26, 17); border-bottom-color: rgb(49, 26, 17); border-left-width: 4px; border-right-width: 4px; border-top-width: 4px; border-bottom-width: 4px; background-color: rgb(110, 57, 37); border-top-left-radius: 15px; border-bottom-left-radius: 15px; border-top-right-radius: 15px; border-bottom-right-radius: 15px; margin-right: 6px;" />
        <ui:VisualElement style="justify-content: space-between; align-items: flex-end;">
            <ui:VisualElement style="align-items: center; background-color: rgb(170, 89, 57); border-left-width: 4px; border-right-width: 4px; border-top-width: 4px; border-bottom-width: 4px; border-left-color: rgb(49, 26, 17); border-right-color: rgb(49, 26, 17); border-top-color: rgb(49, 26, 17); border-bottom-color: rgb(49, 26, 17); border-top-left-radius: 15px; border-bottom-left-radius: 15px; border-top-right-radius: 15px; border-bottom-right-radius: 15px; width: 276px; justify-content: center; padding-left: 8px; padding-right: 8px; padding-top: 8px; padding-bottom: 8px;">
                <ui:VisualElement style="border-left-color: rgb(49, 26, 17); border-right-color: rgb(49, 26, 17); border-top-color: rgb(49, 26, 17); border-bottom-color: rgb(49, 26, 17); border-left-width: 2px; border-right-width: 2px; border-top-width: 2px; border-bottom-width: 2px; height: 120px; width: 120px; border-top-left-radius: 13px; border-bottom-left-radius: 13px; border-top-right-radius: 13px; border-bottom-right-radius: 13px; padding-left: 4px; padding-right: 4px; padding-top: 4px; padding-bottom: 4px; background-color: rgb(255, 133, 84);">
                    <ui:VisualElement name="CharacterPortrait" style="flex-grow: 1; -unity-background-scale-mode: scale-to-fit;" />
                </ui:VisualElement>
                <ui:Label text="Label" name="CharacterName" style="-unity-font-style: bold; font-size: 18px;" />
                <ui:Label text="Label" display-tooltip-when-elided="true" name="CharacterClass" style="margin-top: 2px; margin-bottom: 8px; padding-top: 0; padding-bottom: 0;" />
            </ui:VisualElement>
            <ui:Button text="Select Character" display-tooltip-when-elided="true" name="SelectCharButton" style="width: 150px; border-left-color: rgb(49, 26, 17); border-right-color: rgb(49, 26, 17); border-top-color: rgb(49, 26, 17); border-bottom-color: rgb(49, 26, 17); background-color: rgb(255, 133, 84); border-left-width: 2px; border-right-width: 2px; border-top-width: 2px; border-bottom-width: 2px;" />
        </ui:VisualElement>
    </ui:VisualElement>
</ui:VisualElement>

</ui:UXML>
ListEntry.uxml<ui:UXML xmlns:ui=”UnityEngine.UIElements” xmlns:uie=”UnityEditor.UIElements” editor-extension-mode=”False”>

<ui:VisualElement style="height: 41px; align-items: flex-start; justify-content: center; padding-left: 10px; background-color: rgba(170, 89, 57, 255); border-left-color: rgba(49, 26, 17, 255); border-right-color: rgba(49, 26, 17, 255); border-top-color: rgba(49, 26, 17, 255); border-bottom-color: rgba(49, 26, 17, 255); border-left-width: 2px; border-right-width: 2px; border-top-width: 2px; border-bottom-width: 2px; border-top-left-radius: 15px; border-bottom-left-radius: 15px; border-top-right-radius: 15px; border-bottom-right-radius: 15px;">
    <ui:Label text="Label" display-tooltip-when-elided="true" name="CharacterName" style="-unity-font-style: bold; font-size: 18px;" />
</ui:VisualElement>

</ui:UXML>
字符数据.csusing UnityEngine;

public enum ECharacterClass
{

Knight, Ranger, Wizard

}

[CreateAssetMenu]
public class CharacterData : ScriptableObject
{

public string m_CharacterName;
public ECharacterClass m_Class;
public Sprite m_PortraitImage;

}
字符列表入口控制器.csusing UnityEngine.UIElements;

public class CharacterListEntryController
{

Label m_NameLabel;

public void SetVisualElement(VisualElement visualElement)
{m_NameLabel = visualElement.Q<Label>("CharacterName");
}

public void SetCharacterData(CharacterData characterData)
{m_NameLabel.text = characterData.m_CharacterName;}

}
主视图.csusing UnityEngine;
using UnityEngine.UIElements;

public class MainView : MonoBehaviour
{

[SerializeField]
VisualTreeAsset m_ListEntryTemplate;

void OnEnable()
{
    // The UXML is already instantiated by the UIDocument component
    var uiDocument = GetComponent<UIDocument>();

    // Initialize the character list controller
    var characterListController = new CharacterListController();
    characterListController.InitializeCharacterList(uiDocument.rootVisualElement, m_ListEntryTemplate);
}

}
字符列表控制器.csusing System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

public class CharacterListController
{

// UXML template for list entries
VisualTreeAsset m_ListEntryTemplate;

// UI element references
ListView m_CharacterList;
Label m_CharClassLabel;
Label m_CharNameLabel;
VisualElement m_CharPortrait;
Button m_SelectCharButton;

public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{EnumerateAllCharacters();

    // Store a reference to the template for the list entries
    m_ListEntryTemplate = listElementTemplate;

    // Store a reference to the character list element
    m_CharacterList = root.Q<ListView>("CharacterList");

    // Store references to the selected character info elements
    m_CharClassLabel = root.Q<Label>("CharacterClass");
    m_CharNameLabel = root.Q<Label>("CharacterName");
    m_CharPortrait = root.Q<VisualElement>("CharacterPortrait");

    // Store a reference to the select button
    m_SelectCharButton = root.Q<Button>("SelectCharButton");

    FillCharacterList();

    // Register to get a callback when an item is selected
    m_CharacterList.onSelectionChange += OnCharacterSelected;
}

List<CharacterData> m_AllCharacters;

void EnumerateAllCharacters()
{m_AllCharacters = new List<CharacterData>();
    m_AllCharacters.AddRange(Resources.LoadAll<CharacterData>("Characters"));
}

void FillCharacterList()
{
    // Set up a make item function for a list entry
    m_CharacterList.makeItem = () =>
    {
        // Instantiate the UXML template for the entry
        var newListEntry = m_ListEntryTemplate.Instantiate();

        // Instantiate a controller for the data
        var newListEntryLogic = new CharacterListEntryController();

        // Assign the controller script to the visual element
        newListEntry.userData = newListEntryLogic;

        // Initialize the controller script
        newListEntryLogic.SetVisualElement(newListEntry);

        // Return the root of the instantiated visual tree
        return newListEntry;
    };

    // Set up bind function for a specific list entry
    m_CharacterList.bindItem = (item, index) =>
    {(item.userData as CharacterListEntryController).SetCharacterData(m_AllCharacters[index]);
    };

    // Set a fixed item height
    m_CharacterList.fixedItemHeight = 45;

    // Set the actual item's source list/array
    m_CharacterList.itemsSource = m_AllCharacters;
}

void OnCharacterSelected(IEnumerable<object> selectedItems)
{
    // Get the currently selected item directly from the ListView
    var selectedCharacter = m_CharacterList.selectedItem as CharacterData;

    // Handle none-selection (Escape to deselect everything)
    if (selectedCharacter == null)
    {
        // Clear
        m_CharClassLabel.text = "";
        m_CharNameLabel.text = "";
        m_CharPortrait.style.backgroundImage = null;

        // Disable the select button
        m_SelectCharButton.SetEnabled(false);

        return;
    }

    // Fill in character details
    m_CharClassLabel.text = selectedCharacter.m_Class.ToString();
    m_CharNameLabel.text = selectedCharacter.m_CharacterName;
    m_CharPortrait.style.backgroundImage = new StyleBackground(selectedCharacter.m_PortraitImage);

    // Enable the select button
    m_SelectCharButton.SetEnabled(true);
}

}

正文完
 0