Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
GUI 換膚入門
遊戲必須為玩家提供清晰、資訊豐富且視覺上令人愉悅的使用者介面。雖然 Control 節點預設就有相當實用的外觀,但仍有不少空間可以讓你打造獨特的風格或進行針對性的調整。為此,Godot 引擎內建了 GUI 換膚(或主題)系統,讓你能自訂所有介面控制項的外觀,包括你自訂的控制項。
以下展示此系統的實際效果——一款遊戲的 GUI 與引擎預設的 UI 主題有著截然不同的風格:
《坦克王》中的「裝備起來!」介面,感謝 Winterpixel Games 授權提供
除了為遊戲打造獨特外觀外,這套系統也讓開發者能為終端使用者提供自訂選項,包括無障礙設定。UI 主題是以階層方式套用(也就是會從父控制項向下傳遞到子控制項),這代表像字型設定或色盲相關調整,都能在單一處設定並影響整個 UI 樹狀結構。當然,這套系統也能用於遊戲性設計:像英雄類遊戲可以讓選定角色有不同風格,或團隊遊戲可為不同勢力設計專屬樣式。
主題基礎
換膚系統是由 Theme 資源驅動。每個 Godot 專案都有一個內建的預設主題,包含所有內建控制項預設的外觀設定。這就是控制項預設外觀的來源。不過主題僅僅描述設定,實際如何運用這些設定來顯示,仍取決於各個控制項本身。這點在你實作 自訂控制項 時一定要注意。
備註
連 Godot 編輯器本身也依賴預設主題。但編輯器看起來和一般 Godot 專案不同,因為它在預設主題之上,疊加了高度自訂的主題。原則上這和你的遊戲專案的運作方式完全一樣,詳見 下方說明。
主題項目
儲存在主題中的設定由多個主題項目構成。每個項目都有唯一名稱,且必須屬於下列資料型別之一:
顏色
color 值,常用於字型和背景。顏色也可用於控制項和圖示的調色或變色。
常數
整數值,可用於控制項的數值屬性(例如 BoxContainer 的間距設定),或作為布林旗標(例如 Tree 是否繪製關聯線)。
字型
font 資源,供顯示文字的控制項使用。字型資源本身包含大部分文字算繪設定,但大小和顏色除外。對齊方式與文字方向則是由各控制項自訂。
字型大小
一個整數值,與字型一起決定文字顯示的大小。
圖示
StyleBox
StyleBox 資源,是一組定義 UI 面板顯示方式的設定集合。不只 Panel 控制項使用 StyleBox,許多控制項也都會用於其背景或覆蓋層。
不同控制項會以不同方式套用 StyleBox。特別的是,
focusStyleBox 會被繪製為其他 StyleBox(例如normal或pressed)的*覆蓋層*,以便基礎 StyleBox 仍可見。因此,focus StyleBox 應設計為描邊或半透明樣式,讓底層背景能被保留。
主題型別
為了方便組織管理,各主題會依型別區分,每個項目只能屬於一個型別。換句話說,每個主題項目都由名稱、資料型別與主題型別三者共同決定,這組合在同個主題內必須唯一。例如,Label 型別下不能有兩個叫 font_color 的顏色項目,但 LineEdit 型別下則可有另一個 font_color 項目。
Godot 的預設主題已經定義了多種主題型別,對應所有支援 UI 換膚的內建控制項節點。上面範例中提到的,就是預設主題實際存在的項目。你可以查閱各控制項的類別參考文件中的「主題屬性」章節,了解哪些項目可用於該類別及其子類別。
備註
子類別可以使用父類別定義的主題項目(例如 Button 及其衍生類別)。其實每個控制項理論上都能使用任何型別下的主題項目(但為了清晰性與可預測性,引擎實作上會盡量避免這樣做)。
要注意,對子類別來說這個流程是自動化的。當內建控制項向主題請求主題項目時,可以省略主題型別,會直接使用其類別名稱,接著也會依序查找其父類別名稱。這樣一來,像修改 Button 父類別的主題項目,就能影響所有衍生類別,而無須一一調整。
你也能自訂主題型別,進一步自訂內建控制項或你自己的控制項。不過,內建控制項不會自動識別你的自訂主題型別,因此你必須透過腳本來存取這些項目。所有控制項節點都有多種方法可從當前主題中取得主題項目,這些方法都能接受主題型別作為參數。
var accent_color = get_theme_color("accent_color", "MyType")
label.add_theme_color_override("font_color", accent_color)
Color accentColor = GetThemeColor("accent_color", "MyType");
label.AddThemeColorOverride("font_color", accentColor);
為了提供更多自訂彈性,型別之間也能設計成變種。這是自訂主題型別的另一個應用,例如主題中可以有個 Header 型別,標記為 Label 基礎型別的變種。個別 Label 控制項就可以指定型別為 Header,之後每次請求主題項目時,會優先使用這個變種。這樣就能在同一個 Theme 資源中,為同一類型的控制項儲存不同的主題項目預設值。
警告
只有預設主題或自訂專案主題中的變種,會在屬性檢視器裡顯示為可選項。你仍可手動輸入其他地方定義的變種名稱,但建議所有變種都統一放在專案主題中。
你可以參考 專門的文章,進一步了解主題型別變種的建立與應用。
自訂控制項
每個控制項節點都可以不透過主題而直接自訂,這稱為本地覆寫。你可以在屬性檢視器或用腳本,直接覆寫控制項類別參考中列出的每一個主題屬性。這能讓你細緻調整介面的某一部分,而不影響專案其他部分,包括這個控制項的子項。
本地覆寫對於整體 UI 美觀幫助有限,尤其當你追求一致性時更是如此。不過,對於排版用的節點來說則相當重要。像 BoxContainer 與 GridContainer 這類節點會用主題常數來定義子項間距;MarginContainer 則會將自訂邊界存於主題項目中。
當控制項有本地主題項目覆寫時,會優先使用這個值,主題所提供的值則會被忽略。
自訂專案
每個新專案預設都會採用 Godot 提供的預設專案主題。預設主題本身是固定的、無法修改,但你可以用自訂主題來覆寫它的項目。自訂主題有兩種套用方式:作為專案設定,或設定在控制項樹狀結構中的節點屬性。
有兩個專案設定可以影響整個專案:GUI > Theme > Custom 可設定全專案自訂主題,GUI > Theme > Custom Font 則用於設定預設備援字型。當控制項節點請求主題項目時,會先檢查自訂專案主題(若有設定),只有找不到時才會用預設主題。
這讓你可以用單一主題資源設定所有 Godot 控制項的預設外觀,但你也能做更細膩的調整。每個控制項節點也有 theme 屬性,能針對該節點及其所有子孫節點設定自訂主題。換句話說,這個控制項及其子孫節點會優先檢查這份自訂主題,找不到時才回退到專案主題及預設主題。
備註
你可以選擇不更動專案設定,而是將自訂主題資源設定到 UI 架構中最上層的控制項節點,效果幾乎相同。在專案執行時會如預期顯示,但如果你直接預覽或運行單一場景,則仍會套用預設主題。要解決這問題,可將同一份主題資源,也設定到各個場景的根控制項。
舉例來說,你可以在專案主題設定所有按鈕的統一風格,但希望彈跳視窗裡的按鈕是不同樣式。這時就可以將自訂主題資源設定到該快顯視窗的根控制項,並在主題中為按鈕定義另一種樣式。只要從快顯視窗的根控制項到按鈕之間的節點結構不中斷,這些按鈕就會使用最近的主題資源中定義的樣式。其餘控制項則仍然套用全專案主題與預設主題樣式。
總結來說,任一控制項查找主題項目的流程如下:
檢查是否有相同名稱與資料型別的本地覆寫。
依據控制項的型別變種、類別名稱與父類別名稱:
從自己開始,逐層往上檢查每個控制項是否有設定主題屬性;
如果有,則在該主題檢查有無同名、同型別、同主題型別的項目;
如果沒有自訂主題,或主題中沒有該項目,就往上檢查父控制項;
重複 a-c 步驟,直到場景樹根節點或遇到非控制項節點為止。
若有專案範圍主題,則依型別變種、類別名稱、父類別名稱查找該主題。
依型別變種、類別名稱、父類別名稱查找預設主題。
即使所有主題都找不到該項目,仍會回傳該資料型別的預設值。
控制項以外的應用
主題本身就是用來儲存視覺化設定的理想資源。雖然只有控制項節點內建支援主題,但其他節點也可以像使用其他資源一樣來引用主題。
主題也能應用在控制項以外的場景。例如策略遊戲中,相同單位在不同隊伍時需要不同的顏色顯示,就能用主題資源來定義一組顏色,並透過腳本讓精靈(Sprite)根據主題項目改變顏色繪製貼圖。這樣就能用同一組主題項目,製作紅隊、藍隊、綠隊等不同主題,僅需替換主題資源即可輕鬆切換。