设计图形用户界面

既然你已经掌握了基础知识,我们将看到如何用可重用的UI组件构建一个游戏图形用户界面(GUI):生命条、能量条、炸弹和翡翠计数器。本教程结束时,您将拥有一个游戏图形用户界面,可以使用gdscript或visualscript进行控制:

../../_images/ui_gui_design_final_result.png

最后的结果

您还将学习:

  1. 创建灵活的UI组件

  2. 使用场景继承

  3. 构建复杂的用户界面

下载项目文件: ui_gui_design.zip 提取档案。导入 start/ 在Godot中进行项目以遵循本教程。这个 end/ 文件夹包含最终结果。

注解

您可以将本教程视为 video on Youtube .

分解用户界面

让我们分解最终的用户界面并计划我们将使用的容器。就像在 设计标题屏幕 ,开头是 MarginContainer . 然后,我们可以看到最多三列:

  1. 左边的生命和能量计数器

  2. 生命和能量棒

  3. 右边的炸弹和翡翠柜台

但是这个标签和仪表是同一个UI元素的两部分。如果我们这样想的话,我们只剩下两列:

  1. 左边的生命和能量条

  2. 右边的炸弹和翡翠柜台

这使得嵌套容器更容易:我们在屏幕边界周围使用 MarginContainer ,然后是 HBoxContainer 管理我们的两列。两条钢筋相互叠放在 VBoxContainer . 我们需要最后一个 HBoxContainer 在右栏并排放置炸弹和翡翠柜台。

../../_images/ui_gui_step_tutorial_containers_structure.png

我们得到一个只有4个容器的干净的用户界面布局

我们需要在各个UI组件中额外的容器,但这给了我们主GUI场景的结构。有了这个计划,我们就可以进入Godot并创建我们的GUI。

创建基本GUI

GUI有两种可能的方法:我们可以在不同的场景中设计元素并将它们组合在一起,或者在一个场景中创建所有的原型并稍后将其分解。我建议使用单个场景,因为这样可以更快地播放用户界面的位置和比例。一旦看起来不错,就可以将节点树的整个部分保存为可重用的子场景。我们马上就来。

现在,我们从几个容器开始。

创建新场景并添加 MarginContainer . 选择节点并命名 GUI .

我们希望界面锚定在屏幕顶部。选择 GUI 节点,然后单击视口顶部的布局按钮。选择 Top Wide 选择权。这个 GUI 默认情况下,节点将锚定到其父视图的上边缘。它将在垂直轴上自动调整大小,为其子UI组件留出空间。

将场景另存为 GUI.tscn . 我们将把整个图形用户界面放进去。

MarginContainer 选中后,转到Inspector并向下滚动到“自定义常量”部分。展开它并单击每个 Margin 属性。全部设置为 20 像素。下一步,添加 HBoxContainer 节点。这个将包含我们左边的两个栏,并将它们与右边的两个计数器分开。

我们要将条形图垂直堆叠在 HBoxContainer . 添加一个 VBoxContainer 作为一个孩子 HBoxContainer 并命名它 Bars . 选择父级 HBoxContainer 再一次,这次,再加一个 HBoxContainer 作为它的孩子。叫它吧 Counters . 有了这四个容器,我们就有了GUI场景的基础。

../../_images/ui_gui_containers_structure_in_godot.png

你应该有4个像这样的容器

注解

我们可以这样工作,因为我们首先分解了我们的UI设计,并花了一些时间考虑我们将使用的容器。当你遵循这样的教程时,可能会觉得很奇怪。但一旦你在做真正的游戏,你会发现这是一个有效的工作流程。

创建条形图的基础

每个条形图被拆分为两个子元素,它们水平对齐:左侧带有健康计数的标签,右侧带有仪表。再一次, HBoxContainer 是这项工作的完美工具。选择 Bars 节点并添加新的 HBoxContainer 在里面。命名它 Bar .

标签本身至少需要三个节点:a NinePatchRect 对于背景,在其顶部,我们将在左侧添加纹理,或者 HPEP 和A Label 值的右边。我们可以筑巢 Control 我们想要的节点。我们可以使用 NinePatchRect 作为其他两个元素的父元素,因为它包含了它们。通常,您希望使用容器,因为它们的角色是帮助组织UI组件。我们需要一个 MarginContainer 稍后无论如何要在寿命计数和仪表之间添加一些空间。选择 Bar 添加一个 MarginContainer . 命名它 Count . 在其中添加三个节点:

  1. A NinePatchRect 已命名 Background

  2. A TextureRect 已命名 Title

  3. 和A Label 已命名 Number

要将节点作为兄弟节点添加,请始终选择 Count 首先是节点。

../../_images/ui_gui_step_tutorial_bar_template_1.png

你的场景树应该是这样的。我们准备好加入一些纹理

我们的现场还是空的。是时候加入一些纹理了。要加载纹理,请指向位于视区左侧的文件系统停靠。浏览到res://assets/gui文件夹。

../../_images/ui_gui_step_tutorial_textures_in_FileSystem_tab.png

您应该看到一个纹理列表,我们将使用它来为界面添加皮肤。

选择 Background 在现场码头。在检查员中,你应该看到 Texture 属性。在“文件系统”选项卡中,单击并拖动 label_HP_bg.pngTexture 狭槽。它保持挤压状态。父边缘容器将强制其大小减小到0,直到我们强制容器内的元素具有最小大小。选择 Background 节点。在Inspector中,向下滚动到rect部分。集合 Min Size 到(100,40)。你应该看到 Background 与其父容器一起调整大小。

接下来,选择 Title 拖放 label_HP.png 进入它的 Texture 狭槽。选择 Number 节点,单击 Text 属性和类型 10 . 这样,我们可以在视区中看到两个节点。它们应该堆积在父级的左上角 MarginContainer .

../../_images/ui_gui_step_tutorial_bar_label_stacked.png

如果同时选择两个节点,则应该看到类似的情况

因为它们有一个容器作为它们的直接父容器,所以我们不能自由地移动它们: Count 节点将始终重置其锚定、大小和位置。尝试移动并调整视区中的节点大小。然后,选择三个纹理中的任意一个,然后按Ctrl-Up或Ctrl-Down在“场景停靠”中对它们重新排序。它们将恢复到原来的大小和位置。

父容器控制其直接子容器的大小、比例、页边距和锚定。要修改节点,必须将它们嵌套在常规控件或其他UI元素中。我们将使用 Background 作为家长 TitleNumber . 同时选择 TitleNumber ,并将它们拖放到 Background .

../../_images/ui_gui_step_tutorial_bar_nesting_inside_background.png

通过使用背景节点作为两个纹理的父节点,我们可以从CountMarginContainer获取控制权。

选择 Title 在检查员中,改变 Stretch Mode 属性到 Keep Centered . 下一步查找 Rect 在Inspector中分类并更改 Size 属性设置为(50,40),因此它只取背景的左半部分。接下来,选择 Number 节点。在视区中,单击 Layout 菜单并单击 Full Rect . 节点将调整大小以适应 Background . 向检查员汇报并更换 Align 属性到 RightVAlign 属性到 Center . 文本应对齐到 Background 的右边缘。水平调整节点的大小,使其占用 Background 右边有一些填充物。

../../_images/ui_gui_step_tutorial_bar_placed_title_and_label.png

以下是节点的边界框在视区中的外观。保持粗糙,你现在不需要把它们放得太精确。

替换标签的字体

标签的字体太小。我们需要更换它。选择 Number 在Inspector中,向下滚动到 Control 然后找到 Custom Font 类别。单击 Font 属性并单击 New Dynamic Font . 再次单击该字段并选择“编辑”。

您将进入 Dynamic Font 资源。展开 Font 分类并单击旁边的字段 Font Data . 单击 Load 按钮。在“文件浏览器”中,向下导航到“资产/字体”文件夹,然后双击 Comfortaa-Bold.ttf 打开它。您应该在视区中看到字体更新。展开“设置”类别以更改字体大小。设置 Size 属性设置为更高的值,例如 2428 .

我们现在需要文本的基线,数字的下边缘,来与左侧的HP纹理对齐。这样做,仍然在 DynamicFont 资源,您可以调整 Bottom 财产 Extra Spacing 类别。它在文本中添加了一些底部填充。单击 Number “场景”选项卡中的节点,以返回节点的属性并更改 VAlignBottom . 要调整文本的基线,请单击 Custom Font 再次分类并调整 Bottom 属性,直到文本与 Title 节点。我用了一个值 2 像素。

../../_images/ui_gui_step_tutorial_number_baseline.png

底部值为2像素,数字与标题对齐

有了这个,我们完成了图形用户界面最困难的部分。祝贺你!让我们继续讨论更简单的节点。

添加进度条

我们需要最后一个元素来完成我们的生活吧:测量仪本身。Godot船舶 TextureProgress 拥有我们需要的一切的节点。

选择栏节点并添加 TextureProgress 在里面。命名它 Gauge . 在检查员中展开 Textures 第节。前往文件系统停靠并拖放 lifebar_bg.png 纹理到 Under 狭槽。对…也一样 lifebar_fill.png 把它放到 Progress 狭槽。在 Range 在Inspector类中,更改 Value 属性到 50 要查看仪表是否加满。

只有五个 Control 节点,我们的第一个栏已经准备好使用了。

../../_images/ui_gui_step_tutorial_bar_final.png

就这样,我们的生活吧准备好了。最后一部分很快,不是吗?这要归功于我们强大的容器设置。

设计炸弹和翡翠柜台

炸弹和翡翠柜台就像酒吧 Count 节点。所以我们将复制它并将其用作模板。

Bar 节点,选择 Count 然后按ctrl d复制它。将新节点拖放到 Counters HBoxContainer 在场景树的底部。您应该看到它自动调整大小。暂时别担心,我们很快就会修好尺寸的。

重命名 Count2 节点到 Counter . 与条形图不同,我们希望数字位于左侧,而图标位于右侧。设置是相同的:我们需要一个背景(A NinePatchRect ,标题和编号节点。这个 Title 节点是一个 TextureRect ,所以我们需要显示图标。在场景树中,选择 Title 节点,并将其重命名为 Icon .

../../_images/ui_gui_step_tutorial_counter_design_1.png

下面是到目前为止节点树的外观

Icon 选定的节点,在Inspector中,滚动到顶部以查看 Texture 狭槽。前往左侧的文件系统Dock并选择 bombs_icon.png . 拖放到 Texture 狭槽。在“场景”选项卡中,选择 Icon 以及 Number 节点。单击位于视区顶部工具栏中的布局菜单,然后选择 Full Rect . 两个节点都将更新以适应 Background .

../../_images/ui_gui_step_tutorial_counter_design_2.png

节点定位到整个背景,但其位置为“关闭”。

我们换个 Number 的对齐属性以将其移动到 Background . 选择 Number 节点,更改其 Align 左边的属性和 VAlign 财产归中心。然后稍微调整其左边缘的大小,以便在 Background 以及文本。

../../_images/ui_gui_step_tutorial_counter_design_3.png

编号节点与左侧和中间对齐

要重叠图标和背景,我们需要做一些调整。首先,我们的背景有点高。这是因为它位于一个边缘容器内,由最顶层的GUI节点控制。选择场景树顶部的GUI节点,并垂直缩小,使其尽可能薄。你会看到仪表阻止你把它做得太小。容器不能小于其子容器的最小大小。集装箱的边缘也很重。

选择图标,单击布局菜单,然后选择 Full Rect 重新居中。我们需要它来锚定 Background 的右边缘。再次打开布局菜单并选择 Center Right . 向上移动图标,使其垂直居中 Background .

../../_images/ui_gui_step_tutorial_counter_design_4.png

炸弹图标锚定到背景的右边缘。调整计数器容器的大小,以查看图标节点是否粘附在其右侧

因为我们复制了 Counter 从酒吧里 Count , the Number 节点的字体已关闭。选择 Number 再次节点,前往 Font 属性,然后单击它以访问 DynamicFont 资源。在 Extra Spacing 第节,更改 Bottom 价值到 0 重置字体基线。我们的柜台现在按预期工作。

让我们做 Counters 定位到视区的右边缘。为此,我们需要设置 Bars 容器可以占用所有可用的水平空间。选择 Bars 节点并向下滚动到 Size Flags 类别。在 Horizontal 类别,检查 Expand 值。这个 Bars 节点应调整大小并将计数器推到屏幕右侧。

../../_images/ui_gui_step_tutorial_counter_design_5.png

一个膨胀的容器会从它的父容器中耗尽它所能拥有的所有空间,并在一路上推动其他一切。

将工具栏和计数器转换为可重用的UI组件

我们有一个酒吧和一个柜台小部件。但我们每个都需要两个。稍后我们可能需要更改条形图的设计或功能。如果我们可以有一个场景来存储一个UI元素的模板,并且有一个子场景来处理变体,那就太好了。Godot让我们用继承的场景来做这个。

让我们把两个 Counter 以及 Bar 分支作为单独的场景,我们将减少以创建 LifeBar , the EnergyBar , the BombCounterEmeraldCounter . 选择 Bar HBOX容器。右键单击它并单击 Save Branch as Scene . 将场景另存为 Bar.tscn . 您应该看到节点分支将其转换为单个 Bar 节点。

小技巧

场景是节点树。最上面的节点是树的 root 和层次结构底部的子级是 树叶 . 除了根以外的任何节点以及一个或多个子节点都是 分支 . 我们可以将节点分支封装到单独的场景中,或者将它们从其他场景加载并合并到活动场景中。右键单击场景停靠中的任何节点并选择 Save Branch as SceneMerge from Scene .

然后,选择 Counter 节点并执行相同的操作。右键单击, Save Branch as Scene ,并另存为 Counter.tscn . 新的“编辑场景”图标将显示在场景树中节点的右侧。单击旁边的 Bar 打开相应的场景。调整 Bar 使其边界框适合其内容的节点。按照我们命名和放置控制节点的方式,我们准备继承这个模板并创建生命条。这对 Counter .

../../_images/ui_gui_step_tutorial_bar_template_scene.png

我们的酒吧可以随时使用,没有额外的变化。

使用场景继承创建其余元素

我们需要两个工作方式相同的条:它们的左边应该有一个标签,上面有一些值,右边有一个水平仪。唯一的区别是,一个有HP标签,是绿色的,而另一个被称为EP,是黄色的。Godot为我们提供了一个强大的工具,可以为游戏中的所有酒吧创建一个通用的基础: 继承的场景 .

../../_images/gui_step_tutorial_gui_scene_hierarchy.png

继承的场景帮助我们保持GUI场景的干净。最后,对于每个UI组件,我们只有容器和一个节点。

在继承的场景中,除了名称之外,还可以更改检查器中每个节点的任何属性。如果修改并保存父场景,则所有继承的场景都将更新以反映更改。如果更改继承场景中的值,它将始终覆盖父级的属性。它对UI很有用,因为它们通常需要相同元素的变体。一般来说,在UI设计中,按钮、面板等共享一个公共的基本样式和交互。我们不想手动将其复制到所有变体。

重载图标将出现在您覆盖的属性旁边。单击它可将该值重置为父场景的默认值。

注解

把场景继承想象成节点树,或者 extends gdscript中的关键字。继承的场景执行与其父场景类似的所有操作,但可以覆盖属性、资源并添加额外的节点和脚本以扩展其功能。

继承酒吧场景构建生活吧

Scene -> New Inherited Scene 创建新类型的 Bar . 选择酒吧场景并打开它。你应该看到一个新的 [未保存] 标签,就像你的 Bar ,但所有节点(根除外)均为灰色。出版社 Meta+S 保存新继承的场景并命名 LifeBar .

../../_images/ui_gui_step_tutorial_inherited_scene_parent.png

不能重命名灰色节点。这说明他们有一个父场景

首先,将根节点或顶级节点重命名为 LifeBar . 我们总是希望根目录准确描述这个UI组件是什么。这个名字区别于 EnergyBar 我们将创建下一个。场景中的其他节点应该用广义的术语描述组件的结构,因此它可以处理所有继承的场景。就像我们的 TextureProgressNumber 节点。

注解

如果你曾经做过网页设计,它与使用CSS的精神是一样的:你创建了一个基类,并添加了修改器类的变体。从一个基本按钮类中,您将看到按钮的绿色和红色变化,用户可以接受和拒绝提示。新类包含父元素的名称和一个额外的关键字,用于解释它如何修改它。当我们创建一个继承的场景并更改顶级节点的名称时,我们正在做同样的事情。

设计能量棒

我们已经设置了 LifeBar 的设计 Bar 场景。现在我们需要 EnergyBar .

让我们创建一个新的继承场景,然后再次选择 Bar.tscn 场景并打开。双击 Bar 根节点并将其重命名为 EnergyBar . 将新场景另存为 EnergyBar.tscn . 我们需要用ep one替换hp纹理,并更改仪表上的纹理。

指向左侧的filesystem dock,选择 Title 场景树中的节点,并拖放 label_EP.png 锉到纹理槽上。选择 Number 节点并更改 Text 属性设置为其他值,如 14 .

您会注意到EP纹理比HP纹理小。我们应该更新 Number 的字体大小以更好地适应它。字体是一种资源。整个项目中使用此资源的所有节点都将受到我们更改的任何属性的影响。您可以尝试将大小更改为 40 然后切换回 LifeBarBar 场景。您将看到文本的大小增加。

../../_images/ui_gui_step_tutorial_design_EnergyBar_1.png

如果我们更改字体资源,那么使用它的所有节点都会受到影响。

要仅更改此节点上的字体大小,必须创建字体资源的副本。选择 Number 再次单击节点,然后单击检查器右上角的扳手和螺丝刀图标。在下拉菜单中,选择 Make Sub-Resources Unique 选项。godot会找到这个节点使用的所有资源,并为我们创建唯一的副本。

../../_images/ui_gui_step_tutorial_design_EnergyBar_2.png

使用此选项为一个节点创建资源的唯一副本

小技巧

当从场景树中复制节点时, Meta+D ,它与原始节点共享其资源。你需要使用 Make Sub-Resources Unique 在不影响源节点的情况下调整资源之前。

向下滚动到 Custom Font 剖切和打开 Font . 降低 Size 一个较小的值,比如 2022 . 您可能还需要调整 Bottom 间距值,用于将文本基线与左侧的ep标签对齐。

../../_images/ui_gui_step_tutorial_design_EnergyBar_3.png

ep count小部件,字体比HP小

现在,选择 TextureProgress 节点。拖动 energy_bar_bg.png 文件到 Under 槽和做同样的为 energy_bar_fill.png 把它放在 Progress 纹理槽。

可以垂直调整节点的大小,使其边界矩形适合仪表。对…也一样 Count 直到其大小与条的大小对齐为止。因为最小尺寸 TextureProgress 根据其纹理设置,您将无法缩小 Count 下面的节点。这也是尺寸 Bar 集装箱将有。你也可以缩小这个。

最后但并非最不重要的是, Background 容器的最小尺寸使它有点大。选择它并在 Rect 第节,更改 Min Size 财产减至 80 像素。它应该自动调整大小, TitleNumber 节点也应该重新定位。

../../_images/ui_gui_step_tutorial_design_EnergyBar_4.png

伯爵看起来好多了,现在小一点了

小技巧

计数节点的大小会影响纹理程序的位置。因为我们将在一段时间内垂直对齐条形图,所以最好使用计数器的左边距来调整ep标签的大小。这样,能量条的计数和生命条的计数节点都有100个像素宽,所以两个测量仪将完全对齐。

准备炸弹和翡翠柜台

现在让我们负责柜台。去 Scene -> New Inherited Scene 并选择 Counter.tscn 作为基础。将根节点重命名为 BombCounter 也是。将新场景另存为 BombCounter.tscn . 这就是这场戏的全部内容。

../../_images/ui_gui_step_tutorial_design_counters_1.png

炸弹计数器与原来的计数器场景相同

Scene -> New Inherited Scene 再次选择 Counter.tscn 再次。重命名根节点 EmeraldCounter 并将场景另存为 EmeraldCounter.tscn . 对于这个,我们主要需要用翡翠图标替换炸弹图标。在“文件系统”选项卡中,拖动 emeralds_icon.pngIcon 结点 Texture 狭槽。 Icon 已经锚定到 Background 节点,以便我们可以更改其位置,并且它将随 EmeraldCounter 容器。将翡翠图标向右和向下移动一点。使用键盘上的箭头键微调其位置。保存,所有的UI元素都完成了。

../../_images/ui_gui_step_tutorial_design_counters_2.png

翡翠柜台应该是这样的

将UI组件添加到最终的GUI中

是时候将所有UI元素添加到主GUI场景中了。打开 GUI.tscn 再次场景,并删除 BarCounter 节点。在文件系统基座中,找到 LifeBar.tscn 并将其拖放到 Bars 场景树中的容器。为…做同样的事 EnergyBar . 你应该看到它们垂直对齐。

../../_images/ui_gui_step_tutorial_assemble_final_gui_1.png

生命棒和能量棒自动对齐

现在,拖放 BombCounter.tscnEmeraldCounter.tscn 场景到 Counters 节点。它们会自动调整大小。

../../_images/ui_gui_step_tutorial_assemble_final_gui_2.png

节点调整大小以占用所有可用的垂直空间

EmeraldCounterBombCounter 使用我们在中定义的大小 Counter.tscn ,我们需要改变 Size FlagsCounters 容器。选择 Counters 节点并展开 Size Flags 检查员中的部分。取消选中 Fill 标签 Vertical 属性和检查 Shrink Center 所以容器集中在 HBoxContainer .

../../_images/ui_gui_step_tutorial_assemble_final_gui_3.png

现在两个柜台的尺寸都不错

小技巧

改变 Min Size 性质 Counters 用于控制计数器背景高度的容器。

我们还有一个小问题,那就是能量棒上的EP标签:两个能量棒应该垂直对齐。单击 EnergyBar 节点以打开其场景。选择 Count 节点并向下滚动到 Custom Constants 第节。添加一个 Margin Left 属于 20 . 在 Rect 节设置节点的 Min Size 返回到100,与Lifebar上的值相同。这个 Count 现在应该在左边留一些空白。如果保存并返回到GUI场景,它将与 LifeBar .

../../_images/ui_gui_step_tutorial_assemble_final_gui_4.png

两个横杆完全对齐

注解

我们可以设置 EnergyBar 就在几分钟前。但这向您显示,您可以随时返回任何场景,对其进行调整,并查看通过项目传播的更改!

将图形用户界面放在游戏的模型上

为了总结本教程,我们将把图形用户界面插入到游戏的模型场景中。

前往文件系统Dock并打开 LevelMockup.tscn .

拖放 GUI.tscn 场景就在 bg 节点及以上 Characters . 图形用户界面将缩放以适应整个视区。前往布局菜单并选择 Center Top 选项,使其锚定到游戏窗口的上边缘。然后调整GUI的大小,使其在垂直方向上尽可能小。现在,您可以看到界面在游戏环境中的外观。

恭喜你完成了这个长教程。您可以在此处找到最终项目: ui_gui_design.zip .

../../_images/ui_gui_design_final_result.png

最后的结果

注解

关于响应式设计的最后说明 . 如果调整GUI的大小,您将看到节点移动,但纹理和文本不会缩放。根据图形用户界面内部的纹理,图形用户界面的大小也是最小的。在游戏中,我们不需要像网站那样灵活的界面。您几乎不想同时支持横向和纵向屏幕方向。这是其中之一。在景观方向上,最常见的比例是4:3到16:9。他们彼此很亲近。这就是为什么当我们改变窗口大小时,图形用户界面元素仅仅水平移动就足够了。