利用 Control 節點設計界面

電腦螢幕、手機、電視螢幕等有著不同的形狀與尺寸。要發佈遊戲就需要能支援各種不同的螢幕長寬比與解析度。要製作能適用於所有平台的回應式 (Responsive) 界面有可能很困難。幸好,Godot 提供了強大的工具能夠設計與管理回應式使用者介面。

../../_images/godot_editor_ui.png

Godot 的編輯器是使用引擎的 UI 框架製作的

這篇教學將帶你瞭解 UI 設計。你將學會:

  • 製作遊戲界面最實用的五個 Control 節點

  • 如何使用 UI 元素的錨點

  • 如何使用 Container 有效率地排列與擺放界面

  • 五個最常見的 Container (有關 Container 的更多內容可以參考 GUI Containers 說明文件頁面)。

要學習如何控制界面與將界面與其他腳本連接,請參考 在 Godot 中製作第一個遊戲 UI

要設計 UI,需要使用 Control 節點。Control 節點就是在編輯器中有綠色圖示的節點。Godot 中有數十種的 Control 節點,可以用來製作出血槽甚至是複雜的應用程式等任何的東西。Godot 編輯器本身也是使用 Control 節點製作的。

Control 節點有獨特的屬性能夠,能夠讓一個 Control 節點與另一個 Control 節點互相配合。其他如 Node2D 與 Sprite 的視覺節點就沒有這樣的功能。所以想輕鬆一點的話就請在製作 UI 時儘量使用 Control 節點吧。

所有的 Control 節點都具有這幾個相同的主屬性:

  1. Anchor:錨點

  2. Bouding Rectangle:邊界矩形

  3. Focus 與 Focus Neighbor:焦點與相鄰焦點

  4. Size Flags:大小標誌

  5. Margin:外邊距

  6. 可選的 UI 主題

瞭解了 Control 節點的基礎後,以後學習其他從 Control 節點衍生而來的其他節點就能更快速。

五個最常見的 UI 元素

Godot 附帶了數十種 Control 節點。而其中許多節點都是用來讓你可以製作編輯器外掛與應用程式的。

對於大多數的遊戲來說,只會需要五種 UI 元素以及少數幾個 Container。這五個 Control 節點為:

  1. Label:標籤,用來顯示文字

  2. TextureRect:紋理貼圖矩形,通常用來作背景,或是其他顯示靜態圖片的地方

  3. TextureProgress:紋理貼圖進度條,用於血槽、載入進度條,可以是任何水平、垂直、或放射性的

  4. NinePatchRect:9-Patch 矩形,用於可縮放的面板

  5. TextureButton:紋理貼圖按鈕,用於製作按鈕

../../_images/five_most_common_nodes.png

用於 UI 設計的五個最常見的 Control 節點

TextureRect

TextureRect 可以在 UI 中顯示紋理貼圖或圖片。看起來很像 Sprite 節點,但 TextureRect 提供了多種縮放模式。修改 Stretch Mode(拉伸模式)屬性即可更改行為:

  • Scale On Expand (compat) :延展時縮放(相容),僅當 expand 屬性設為 true 時將紋理貼圖縮放至符合節點的邊界矩形。其餘情況則與 Keep 模式行為相同。為向下相容性,該模式為預設。

  • Scale :縮放,將紋理貼圖縮放至節點的邊界矩形。

  • Tile :平鋪,重複紋理貼圖,但不進行縮放。

  • KeepKeep Centered :保持與保持居中,強制紋理貼圖保持原始大小,分別置於框架的左上角或中間。

  • Keep AspectKeep Aspect Centered :保持長寬比與居中保持長寬比,將紋理貼圖縮放但強制其維持原始的長寬比,分別置於框架的左上角或中間。

  • Keep Aspect Covered :保持長寬比覆蓋,行為與 Keep Aspect Centered 相同,但短邊會配合邊界矩形,另一邊則會超出節點邊界並剪裁掉。

與 Sprite 節點一樣,TextureRect 的顏色也可以調整。點擊 Modulate (調變)屬性後使用色彩選擇器。

../../_images/five_common_nodes_textureframe.png

使用紅色調變的 TextureRect

TextureButton

TextureButton 類似 TextureRect,不同的地方是 TextureButton 有六個紋理貼圖欄位,每個按鈕的狀態都有一個貼圖。大多數情況下,會使用到 Normal (正常)、Pressed (按下) 與 Hover (懸停) 的貼圖。Focused (聚焦) 適用於會監聽鍵盤事件的界面。第六個圖片欄位為 Click Mask (點擊遮色片),可使用 1-Bit 的純黑白圖片來定義可點擊的區域。

在 Base Button 的部分有幾個勾選框可以改變按鈕的行為。當開啟 Toggle Mode (切換模式)時,點擊按鈕時會在啟用 (Active) 與正常 (Normal) 狀態間切換。 Disabled (禁用)會讓按鈕在預設時禁用,這時候會使用 Disabled 紋理貼圖。TextureButton 也有一些與紋理框架相同的屬性: Modulate (調變)屬性可更改色彩, Resize (調整大小)與 Stretch (伸縮)模式可以更改其縮放的行為。

../../_images/five_common_nodes_texturebutton.png

TextureButton 與其五個紋理貼圖欄位

TextureProgress

TextureProgress 可使用最多三個圖層的 Sprite 來建立進度條。 Under 與 Over 紋理貼圖中間夾著顯示進度條數值的 Progress 貼圖。

Mode 屬性可以控制進度條的方向:水平、垂直、或放射狀。若設為放射狀,則可使用 Initial Angle (初始角度)與 Fill Degress (填充角度)來限制放射的範圍。

若要在進度條中使用動畫,可使用 Range 下的屬性。 MinMax 屬性可用來定義進度條的範圍。舉例來說,角色的血槽可以設定 Min 為 0,而 Max 則根據角色的最大生命來設定。更改 Value 屬性即可更新進度條。若將 MinMax 設為預設的 0100 ,則將 Value 屬性設為 40 ,則將顯示 40% 的 Progress 紋理貼圖,剩下 60% 保持不顯示。

../../_images/five_common_nodes_textureprogress.png

TextureProgress 進度條,填滿三分之二

標籤

Label 將文字顯示在畫面上。所有的屬性都列屬性面板中的 Label 段落下。文字可寫在 Text 屬性裡,而若要依據文字框的大小來調整,則可勾選 Autowrap(自動斷行)。若關閉 Autowrap,則將無法縮放節點。可以使用 Align(對齊)與 Valign(垂直對齊)屬性來調整文字在垂直與水平方向的對齊方法。

../../_images/five_common_nodes_label.png

Label 的圖片

NinePatchRect

**NinePatchRect`` 將紋理貼圖分隔成三行三列。中間與側面的貼圖會在縮放貼圖時平鋪,而角落的貼圖則不會被縮放。適合用來製作 UI 中的面板、對話框、與可伸縮的背景。

../../_images/five_common_nodes_ninepatchrect.png

使用 min_size 屬性縮放的 NinePatchRect

製作回應式 UI 的兩個工作流程

在 Godot 中有兩個工作流程可用來建立可擴充與彈性的界面:

  1. Place UI elements precisely with anchors: Use the Layout menu to place and resize a UI element relative to its parent.

  2. Arrange control nodes automatically with containers: Use container nodes to automatically scale and place UI elements.

這兩種方法並非完全相容。由於 Container 會控制其子節點,所以無法在 Container 節點上使用畫面配置選單。各種 Container 都有特定的效果,所以製作界面時就會需要嵌套多層 Container。若使用畫面配置選單的話,就能由下至上地 (Bottom Up) 從子節點開始製作界面,因為不需要額外在場景中插入 Container,所以架構也會比較清楚。但這種方式也比較難能以行、列、或以網格系統等方式來排列 UI。

在為遊戲與工具建立 UI 後你就能漸漸掌握各種狀況下要用什麼方式最適合。

使用錨點精確地擺放 UI 元素

Control 節點有位置與大小,同時也有錨點與外邊距。錨點定義相對於節點左邊 (Left)、上面 (Top)、右邊 (Right)、與下面 (Bottom) 的原點(或稱為參考點)。更改這四個錨點即可更改外邊距的參考點。

../../_images/anchor_property.png

錨點屬性

如何更改錨點

與其他屬性一樣,可以在屬性面板中編輯四個錨點。但這種方法不是最方便的。當選擇一個 Control 節點後,檢視區上方的工具列會出現畫面配置選單。通過畫面配置選單中的各個圖示,就只需要點擊一下便可設定四個錨點值,而不需自己在屬性面板中調整。畫面配置選單只會在選擇 Control 節點後出現。

../../_images/layout_menu.png

檢視區中的畫面配置選單

節點相對於其母容器

每個錨點的值都介於 0 與 1。左邊 (Left) 與上面 (Top) 的錨點中,值為 0 則代表沒有任何外邊距。節點的邊距會保持與母節點中的左側與上面的邊緣對齊。而右邊 (Right) 與下面 (Bottom) 的錨點,值為 1 則代表會與母容器的右邊與下面的邊緣對齊。換句話說,外邊距代表了至錨點的距離,單位為像素。而錨點則是相對於母容器的大小。

../../_images/ui_anchor_and_margins.png

外邊距相對於錨點位置,而錨點位置則相對於錨點。在實務上通常會使用容器來更新邊距

外邊距會跟著錨點變化

外邊距會自動在移動或縮放 Control 節點時更新。外邊距表示從節點邊緣至錨點的距離,錨點則相對於母 Control 節點或母 Container 節點。這就是為什麼應該要把 Control 節點放在 Container 內的原因,我們稍後會討論到這點。若沒有母節點時,外邊距會相對於節點自己的定界 Rectangle。該值設定於屬性面板中的 Rect 段落下。

../../_images/control_node_margin.png

在 CenterContainer 設定「 Full Rect 」錨點的外邊距

試著更改錨點或將 Control 節點嵌套於 Container 內後會發現外邊距跟著更新。通常外邊距不需要手動修改。首先應該找找有沒有適合的 Container,Godot 有許多能解決所有常見情況的節點:需要在血槽與畫面邊緣間加點空白?可以用 MarginContainer。要製作垂直選單?可以使用 VBoxContainer。更多詳細資訊請參考下文。

使用大小標籤來改變 UI 元素填充空間的方式

所有的 Control 節點都有大小旗標 (Size Flag)。這些旗標用來控制 Container 如何縮放其中的 UI 元素。若在 Horizontal(水平)或 Vertical(垂直)屬性上新增「Fill」旗標,則節點的定界框會佔用所有可用的空間,但同時也會顧慮其他同級節點並保留同級節點的大小。若在兩個方向都設定了「Fill」旗標的 HBoxContainer 中有三個 TextureRect 節點,則這三個節點都只會佔用最多三分之一的可用空間。Container 會控制節點並自動縮放這些節點。

../../_images/textureframe_in_box_container_fill.png

HBoxContainer 中的三個 UI 元素,水平對齊

「Expand」旗標會讓 UI 元素佔滿所有可用的空間,並擠壓同級元素。定界框會一直沿著母節點的邊緣增長,除非被另一個 UI 元素阻擋。

../../_images/textureframe_in_box_container_expand.png

與上方的範例相同,但中間的節點加上了「 Expand 」大小旗標

要瞭解大小旗標需要一些練習,因為設定大小旗標的效果會根據設定界面方式的不同而有很大的不同。

使用 Container 來自動排列 Control 節點

Container 會自動以行列形式排列包含其他 Container 在內的所有子 Control 節點。使用 Container 節點來在界面周圍新增內邊距 (Padding) 或是用來將節點在定界框內置中。所有內建的 Container 都會在編輯器內更新,所以所有改動都會立即反映。

Container 有一些用來控制如何排列 UI 元素的特殊屬性。要修改這些屬性,請看到屬性面板中的 Custom Contants(自定常數)段落。

五個最實用的 Container

在製作工具的時候可能會需要用到所有的 Container。但大多數遊戲只需要其中幾種就夠了:

  • MarginContainer, to add margins around parts of the UI

  • CenterContainer,置中容器,用來將子元素放在定界框中間

  • VboxContainer 與 HboxContainer,垂直框容器與水平框容器,用來以行或列排列 UI 元素

  • GridContainer,柵欄容器,用來以類似柵欄系統的方式排列 Control 節點

CenterContainer 會將所有子節點置中與其定界框內。標題畫面通常會使用到這個容器,或是要將選項放在檢視區的中間時使用。CenterContainer 會將所有東西都置中,所以通常會在裡面嵌套另一個容器。若改用紋理貼圖或按鈕,則會堆疊在一起。

../../_images/five_containers_centercontainer.png

實際使用 CenterContainer 的例子。血槽放置於母容器中。

MarginContainer 會在子節點的每個邊都加上外邊距。新增一個圍繞整個檢視區的 MarginContainer 即可為視窗邊緣與 UI 之間加上空白。可以在容器的上右下左各個邊緣都加上外邊距。不需要勾選勾選框:只需點擊相應的數值輸入框並輸入任何數字,之後會自動啟用。

../../_images/five_containers_margincontainer.png

MarginContainer 在遊戲 UI 的周圍加上了 40px 的外邊距

有兩種 BoxContainer:VBoxContainer 與 HBoxContainer。由於 BoxContainer 屬於 Helper 類別,所以 BoxContainer 無法直接使用。可以使用垂直與水平的 Box Container。這兩個 Container 會以行或列的形式來排列子節點。可使用這兩種容器來排列商店裡的物品、或是依照你所想像的方式進行嵌套來建立有不同大小的行與列的複雜柵欄系統。

../../_images/five_containers_boxcontainer.png

HBoxContainer 水平對齊 UI 元素

VBoxContainer 自動會一個列中排列子節點的,將各個節點一個接一個排放。若使用 Speration(分隔)參數,則會在子節點間加上間隔。HBoxContainer 則會在一行間排列子節點,並且可使用額外的 add_spacer 方法來在腳本中為第一個子節點前或最後一個子節點後新增 Spacer Control 節點。

GridContainer 可以用類似柵欄系統的方式來排列 UI 元素。其中只有列數能控制,行數會自動依據子節點的數量來調整。若有九個子節點,列數設為三,則最後會有 9÷3 = 3 行。再新增三個子節點則會變成四行。換句話說,每當新增了更多紋理貼圖與按鈕後行數也會隨之增加。如同 Box 容器,GridContainer 有兩個屬性分別用來設縱向的行間隔與橫向的列間隔。

../../_images/five_containers_gridcontainer.png

有兩個列的 GridContainer。各個列的大小為自動設定的。

Godot 的 UI 系統很複雜,且除了此處提到的之外還有更多。欲瞭解如何設計更多進階的界面,請參閱說明文件中的 GUI 段落