Unity3D :为运行时创建选项卡式菜单
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
为运行时创建选项卡式菜单
版本: 2021.3+
选项卡式菜单在视频游戏和应用程序中很常见用户界面
.可以使用 UI 工具包为自定义编辑器窗口或运行时创建选项卡式菜单。此示例演示如何在示例中创建选项卡式菜单现场
.
示例概述
本示例在示例场景中添加一个菜单。菜单有三个选项卡。每个选项卡都显示某些内容。单击选项卡时,仅显示与该选项卡关联的内容。
要创建选项卡式内容,您需要定义菜单元素、样式和逻辑。
您可以在此 GitHub 存储库中找到此示例创建的已完成文件。
先决条件
本指南适用于熟悉 Unity、UI 工具包、弹性框和 C# 脚本的开发人员。在开始之前,请熟悉以下内容:
- 标签
- 美国航空母舰
- 用户界面生成器
- 使用弹性框定位元素
定义选项卡式菜单元素
使用 UI 生成器在菜单中创建两个部分,一个用于选项卡,一个用于选项卡的内容。在这些部分中,创建三个选项卡元素和三个选项卡内容元素。
- 使用任何模板在 Unity 中创建项目。
- 单击“游戏对象”>“UI 工具包”>“UI 文档”以在示例场景中添加 UI 文档。
- 在 中创建一个文件夹以存储所有文件。
AssetsTabbedMenu
- 在该文件夹中,创建名为 的 UI 文档。
TabbedMenuTabbedMenu.uxml
- 双击以在 UI 生成器中将其打开。
TabbedMenu.uxml
- 在根目录下添加两个名为 和 的可视元素。
tabstabContent
在 下,添加三个标签控件,并为其提供以下标签文本:tabs
London
Paris
Ottawa
在 下,添加三个标签控件,并为其提供以下标签文本:tabContent
London is the capital city of England
Paris is the capital of France
Ottawa is the capital of Canada
若要将选项卡内容与选项卡相关联,此示例对标签名称使用相同的前缀,但后缀不同。每个选项卡名称都有后缀,每个选项卡内容都有后缀。将选项卡标签名称和内容标签名称设置为以下内容:TabContent
LondonTab
ParisTab
OttawaTab
LondonContent
ParisContent
OttawaContent
您的 UI 生成器层次结构如下所示:
定义选项卡式菜单样式
使用 USS 定义选项卡和选项卡内容的布局。您可以按照自己喜欢的方式设置选项卡和选项卡内容的样式。本示例将制表符排成一行并排在制表符内容的顶部。它为所选选项卡添加背景色,并隐藏未选择的选项卡内容。
- 在该文件夹中,创建名为 的样式表。
TabbedMenuTabbedMenu.uss
- 打开并添加以下样式规则:
TabbedMenu.uss
/* Style for tabs */
tabs {
flex-direction: row;
background-color: rgb(229, 223, 223);
-unity-font-style: bold;
font-size: 14px;
}
/* Sets each label in tabs to have the same size. */
.tab {
flex-grow: 1;
}
/* Adds background color for the selected tab */
.currentlySelectedTab {
background-color: rgb(173, 166, 166);
}
/* Style for tabContent */
tabContent {
background-color: rgb(255, 255, 255);
font-size: 20px;
}
/* Hides the unselected tab content */
.unselectedContent {
display: none;
}
3. 在 UI 生成器中打开。TabbedMenu.uxml
4. 单击添加现有 USS,然后选择 。TabbedMenu.uss
5. 将样式应用于 UI 控件:
- 应用于下的每个标签
.tabtabs
- 适用于
.currentlySelectedTabLondonTab
- 适用于和
.unselectedContentParisContentOttawaContent
完成的内容如下所示:TabbedMenu.uxml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
/* Your src might look different. If you save your UXML in UI Builder, USS file is referenced by the file location, fileID and guid. */
设置场景
创建用户界面目录游戏对象
,并将 UI 文档添加为源资源。
- 在示例场景中,选择“游戏对象> UI 工具包”>“UI 文档”。
- 在层次结构中选择 UIDocument 游戏对象,然后从您的项目窗口
到 UI 文档组件的“源资产”字段检查员
窗。这会将源资源引用到您创建的 UXML 文件。
定义选项卡式菜单逻辑
创建更改显示的选项卡内容的 C# 脚本。当用户单击选项卡时,将显示选项卡的内容并隐藏当前内容。创建一个将选项卡式菜单逻辑附加到游戏的 MonoBehavior 脚本。
- 在该文件夹中,创建一个名为以下内容的 C# 脚本:
TabbedMenuTabbedMenuController.cs
// This script defines the tab selection logic.
using UnityEngine.UIElements;
public class TabbedMenuController
{
/* Define member variables*/
private const string tabClassName = "tab";
private const string currentlySelectedTabClassName = "currentlySelectedTab";
private const string unselectedContentClassName = "unselectedContent";
// Tab and tab content have the same prefix but different suffix
// Define the suffix of the tab name
private const string tabNameSuffix = "Tab";
// Define the suffix of the tab content name
private const string contentNameSuffix = "Content";
private readonly VisualElement root;
public TabbedMenuController(VisualElement root)
{
this.root = root;
}
public void RegisterTabCallbacks()
{
UQueryBuilder<Label> tabs = GetAllTabs();
tabs.ForEach((Label tab) => {
tab.RegisterCallback<ClickEvent>(TabOnClick);
});
}
/* Method for the tab on-click event:
- If it is not selected, find other tabs that are selected, unselect them
- Then select the tab that was clicked on
*/
private void TabOnClick(ClickEvent evt)
{
Label clickedTab = evt.currentTarget as Label;
if (!TabIsCurrentlySelected(clickedTab))
{
GetAllTabs().Where(
(tab) => tab != clickedTab && TabIsCurrentlySelected(tab)
).ForEach(UnselectTab);
SelectTab(clickedTab);
}
}
//Method that returns a Boolean indicating whether a tab is currently selected
private static bool TabIsCurrentlySelected(Label tab)
{
return tab.ClassListContains(currentlySelectedTabClassName);
}
private UQueryBuilder<Label> GetAllTabs()
{
return root.Query<Label>(className: tabClassName);
}
/* Method for the selected tab:
- Takes a tab as a parameter and adds the currentlySelectedTab class
- Then finds the tab content and removes the unselectedContent class */
private void SelectTab(Label tab)
{
tab.AddToClassList(currentlySelectedTabClassName);
VisualElement content = FindContent(tab);
content.RemoveFromClassList(unselectedContentClassName);
}
/* Method for the unselected tab:
- Takes a tab as a parameter and removes the currentlySelectedTab class
- Then finds the tab content and adds the unselectedContent class */
private void UnselectTab(Label tab)
{
tab.RemoveFromClassList(currentlySelectedTabClassName);
VisualElement content = FindContent(tab);
content.AddToClassList(unselectedContentClassName);
}
// Method to generate the associated tab content name by for the given tab name
private static string GenerateContentName(Label tab) =>
tab.name.Replace(tabNameSuffix, contentNameSuffix);
// Method that takes a tab as a parameter and returns the associated content element
private VisualElement FindContent(Label tab)
{
return root.Q(GenerateContentName(tab));
}
}
2. 在该文件夹中,创建一个名为以下内容的 C# 脚本:TabbedMenuTabbedMenu.cs
// This script attaches the tabbed menu logic to the game.
using UnityEngine;
using UnityEngine.UIElements;
//Inherits from class MonoBehaviour
. This makes it attachable to a game object as a component.
public class TabbedMenu : MonoBehaviour
{
private TabbedMenuController controller;
private void OnEnable()
{
UIDocument menu = GetComponent<UIDocument>();
VisualElement root = menu.rootVisualElement;
controller = new(root);
controller.RegisterTabCallbacks();
}
}
3. 在 SampleScene 中选择 UIDocument,然后拖动 以在检查器中添加组件。TabbedMenu.cs
4. 进入播放模式,然后单击不同的选项卡以查看不同的内容。
由3D建模学习工作室整理翻译,转载请注明出处!