從 Unity 到 Godot Engine

本指南以 Unity 使用者的角度來介紹 Godot Engine,旨在幫助你把現有的 Unity 體驗遷移至 Godot 的世界中。

備註

這篇文章討論的是舊版的 Unity。可嵌套的 Prefabs(「Nested prefabs」)在 Unity 2018.3 中新增。Nestable prefbas 類似於 Godot 的場景,並允許使用類似 Godot 的方式來組織場景。

差異

Unity

Godot

授權條款

專屬軟體、封閉原始碼、有限制收入上限與使用限制的免費授權條款

MIT 授權條款,免費自由且完全開放原始碼而不帶任何限制

作業系統(編輯器)

Windows、macOS、Linux

Windows、macOS、X11(Linux、*BSD)

作業系統(匯出)

  • 桌面平台: Windows、macOS、Linux

  • 行動裝置: Android、iOS、Windows Phone、Tizen

  • 網頁: WebAssembly 或 asm.js

  • 遊戲主機: PS4、PS Vita、Xbox One、Xbox 360、Wii U、Nintendo 3DS

  • VR: Oculus Rift、SteamVR、Google Cardboard、PlayStation VR、Gear VR、HoloLens

  • TV: Android TV、Samsung SMART TV、tvOS

  • 桌面平台: Windows、macOS、X11

  • 行動裝置: Android、iOS

  • 網頁: WebAssembly

  • 遊戲主機: 請參閱 Console support in Godot

  • VR: Oculus Rift、SteamVR

場景系統

  • 元件/場景 (遊戲物件 > 元件)

  • Prefabs

場景樹與節點 ,可允許場景互相嵌套與/或繼承其他場景

第三方工具

Visual Studio 或 VS Code

特色優點

  • 龐大的社群

  • 豐富的素材商店

編輯器

Godot Engine 提供了用來製作遊戲的功能豐富的編輯器。下圖顯示了兩種編輯器預設的畫面配置,使用色塊來區分共通的功能。

../../_images/unity-gui-overlay.png ../../_images/godot-gui-overlay.png

雖然兩個編輯器看起來有點像,但實際上卻有許多的不同。兩者都可以使用檔案系統來管理專案,但 Godot 的做法比較簡單而且只使用了單一組態設定檔、極簡的純文字格式、且不使用後設資料。這麼做使得 Godot 對如 Git、Subversion、或 Mercurial 等的 VCS 系統更加友善。

Godot 的場景面板與 Unity 的 Hierarchy 面板類似,但由於每個節點都有特定的功能,Godot 使用的方法在視覺上比較直覺。對於場景是用來做什麼的總可以一目瞭然。

Godot 的屬性面板則比較簡單,只顯示了屬性。但多虧於此,物件可以將更實用的參數暴露給使用者而毋須以語言 API 來隱藏功能。另外,Godot 也允許視覺動畫化任何一個屬性。更改色彩、紋理貼圖、或甚至可以即時動態串聯資源而毋須撰寫程式碼。

上方的工具列在兩個編輯器上也很類似,都提供了控制專案執行的功能。在 Godot 中的專案是以分開的視窗執行的,而不是在編輯器中執行(但場景樹與物件仍然可以在偵錯視窗中瀏覽)。

這樣的做法有許多優點:

  • 可快速執行專案與關閉專案(Unity 上必須先保存、執行專案、關閉專案、然後恢復前一個狀態)。

  • 更實用的是即時編輯功能,因為在編輯器上做的改動會直接立即影響遊戲,且遊戲關閉時也不會遺失改動(也不需同步)。這樣一來便能有出色的工作流程,如在執行遊戲時同時編輯關卡。

  • 更穩定的編輯器,因遊戲執行於獨立的處理程序。

  • 可以通過打開編輯器檢視區中的「相機覆蓋」按鈕來以不同的角度瀏覽正在執行的遊戲,這個按鈕能在編輯器視圖與遊戲相機視圖間切換。

最後,Godot 的頂部工具列包含了用於遠端除錯的選單。選單中的選項包含可部署至裝置(如通過 HTML5 連接的手機、平板、或瀏覽器),並在遊戲匯出後進行除錯與即時編輯。

場景系統

場景系統是 Unity 與 Godot 間最大的不同,也是許多 Godot 使用者最喜歡的功能。

在 Unity 中製作「關卡」通常表示必須要將所有需要的素材都嵌入至場景內,並將這些素材與元件、腳本關聯在一起。

Godot 的場景系統表面上看起來與 Unity 類似。「關卡」是由具有不同目的的節點組成的,如 Sprite、Mesh、Light…等。而且,在 Godot 中節點是由樹狀結構組織的,每個節點都可有多個子節點,所以每個節點都是主要場景的子場景。這代表可用保存在不同檔案中的不同場景來組織成整個場景。

以平台遊戲的關卡為例,可以用多個元素來組成:

  • 磚塊

  • 金幣

  • 玩家

  • 敵人

在 Unity 中我們會在場景中放置所有的 GameObjects:放置玩家、多個敵人的實體,到處放置磚塊來組成關卡的地面,在關卡各處放置多個金幣的實體。接著將不同的元件關聯到各個元素上並為關卡加入邏輯,舉例來說,為場景中所有的元素都加上 BoxCollider2D 來製作碰撞。在 Godot 中則會用不同的概念。

Godot 裡會將這整個場景拆分為三個獨立的小場景,接在再於主場景中實體化。

  1. 只有玩家的場景。

我們可以把玩家想像成一個要放在不同母場景(如「關卡」場景)中的元素。在這個例子中,要製作一個玩家元素至少需要使用到 AnimatedSprite 節點。這個節點包含了用於數種動畫的 Sprite 紋理(如走路的動畫)。

  1. 敵人場景。

敵人也會需要用在多個場景內,大部分都跟玩家節點一樣。不同的地方只有腳本(敵人需要有一點「AI」來產生行為)以及 AnimatedSprite 節點用到的 Sprite 紋理。

  1. 關卡場景。

關卡場景是由磚塊(製作平台用)、硬幣(給玩家蒐集用)、以及數個敵人場景的實體所組成的。各個實體都是關卡場景樹內的一個節點。這些實體就是獨立的敵人,這些敵人的初始行為與外觀都是一樣的,由敵人場景所定義。我們可以為每個敵人節點設定不同的屬性(如更改顏色)。

4. A Main scene. The Main scene would be composed of one root node with 2 children: a Player instance node, and a Level instance node. The root node can be anything, generally a "root" type such as "Node" which is the most global type, or "Node2D" (root type of all 2D-related nodes), "Spatial" (root type of all 3D-related nodes) or "Control" (root type of all GUI-related nodes).

就像這樣,所有場景都以樹狀結構來組織。節點的屬性也一樣:我們不像 Unity 那樣給節點 加上 碰撞元件來讓元件可碰撞,而是將節點設為有碰撞屬性節點的 子節點 。Godot 根據用途的不同,提供了多種碰撞型別節點(請參考 物理系統介紹 )。

  • 這個系統有什麼優點?這套系統用到最後不會一直增加場景樹的深度嗎?而且 Unity 不是可以在空的 GameObject 裡放 GameObject 來組織嗎?

    • Godot 的系統與大名鼎鼎的物件導向類似:Godot 提供了數種節點明顯就不是「遊戲物件 (Game Object)」,但這些節點能將自己的功能提供給子節點:這就是繼承。

    • 在 Godot 中可以將場景的某個子樹獨立變成一個場景。所以當場景樹變得太深的時候可以將其切割為幾個小子樹。這樣一來可重複性也變得更好,因為任何節點都可以新增任何子樹為子節點。在 Unity 中將多個 GameObject 放到一個空的 GameObject 中並不會有相同的效果。

組織專案

../../_images/unity-project-organization-example.png

沒有一種專案架構是最完美的。各種不同的架構都可以在 Unity 與 Godot 內使用。

然而,Unity 專案常見的架構為在根目錄放一個 Assets 資料夾,裡面包含給不同素材的各個資料夾:Audio、Graphics、Models、Materials、Scripts、Scenes…等。

由於 Godot 內可以將場景切分為許多小場景,各個場景與子場景在專案裡都作為檔案存在,所以我們建議你用稍微不同的方式來組織專案。這篇 Wiki 為此提供了一頁: 組織專案

Prefabs 跑去哪了?

Unity 中的 Prefabs 是場景中的一個「樣板」元素。可以重複使用,且存在於場景中的各個 Prefab 實體都有自己的存在,但這些所有的實體都共用 Prefab 裡定義的屬性。

Godot 沒有這樣的 Prefab,但場景系統提供了相同的功能:場景系統以樹狀結構組織。Godot 內可以將場景的任何子樹保存為場景檔案,新的場景可以被任意實體化作為任何節點的子節點。對新場景的改動會套用到所有的實體上,但對實體做的改動不會影響到「樣板」場景。

../../_images/save-branch-as-scene.png

講得更精確一點,我們可以在屬性面板中修改一個實體的參數。構成這個實體的節點預設是鎖定的,若有需要則可以在場景樹中右鍵點擊實體並在選單中選擇「可編輯子節點」來解鎖。若要往該節點 新增 子節點則不需要解鎖,但要記得新的子節點是屬於實體的而不是保存在硬碟上的「樣板」場景。如果「樣板」場景的每個實體都需要新增子節點的話,那應該把子節點加在「樣板」場景內。

../../_images/editable-children.png

對應的術語

  • GameObject -> Node(節點)

  • 新增元件 -> 繼承

  • Prefab -> 可重複使用的場景檔

撰寫腳本:GDScript、C#、與視覺腳本 (VisualScript)

設計

Unity 支援 C#,C# 收益於與 Visual Studio 的整合,且擁有如靜態型別等理想的功能。

Godot 提供了自己的腳本語言 GDScript ,同時也支援 視覺腳本 (VisualScript) 以及 C# 。GDDScript 雖然從 Python 借來了語法結構,但與 Python 並無關聯。若你想瞭解為什麼我們使用了自己的腳本語言,請參考 GDScript 基礎常見問題 頁面。GDScript 與 Godot API 的緊密整合,且不需花費太多時間來學習,對於有經驗的程式設計師只需要花一個晚上,完全的新手花一個星期的時間即可上手。

Unity 允許在 GameObject 上附加任意數量的腳本,每個腳本都會為 GameObject 增加行為。舉例來說,可以新增一個用來對應玩家控制的腳本,而另一個用來控制特定的遊戲邏輯。

在 Godot 中,每個節點都只能附加一個腳本,可以使用外部 GDScript 檔案或是直接在節點中包含腳本。若需要對一個節點附加超過一個的腳本,則可以依據場景與目的考慮兩種解決方法:

  • 在目標節點與目前的母節點間再新增一個節點,然後將腳本附加到新建立的節點上。

  • 將目標節點拆分成多個子節點,然後為每個節點都附加一個腳本。

就像這樣,場景樹可能很容易變得很亂。可以考慮將複雜的場景拆分成多個較小的分支。

連接:群組與訊號

可以通過腳本或是直接呼叫節點上的內建或使用者定義的函式來控制節點。也可以將節點放在群組中,然後呼叫這個群組中所有節點的函式。更多資訊請參考 腳本文件

節點可以在特定行為發生的時候送出訊號。訊號可以設定來呼叫任何函式。也可以自己定義自定訊號並指定觸發的時機。詳細請參考 訊號文件

腳本序列化

Unity 可通過兩種方法來處理腳本的序列化 (Serialization):

  • 隱含:若型別為可序列化的型別,則類別中所有 Public 欄位都會自動序列化( Dictionary 不可序列化)。

  • 明確:非 Public 欄位可使用 [SerializeField] 屬性來序列化。

Godot 有內建的腳本序列化系統,但只會在明確聲明下運作。任何可序列化的型別都可使用 export 關鍵字來序列化( 內建與各種引擎型別 ,包含 ArrayDictionary)。詳細請參考 Export 文件

Unity 還有一個用來序列化素材物件的 ScriptableObject 資料型別。這個型別同等於 Godot 中所有資源的基礎型別 Resource 。建立一個繼承 Resource 的腳本即可建立可序列化的自定物件。更多關於資源的資訊可參考 這裡

在 Godot 中使用 C++

Godot 可以讓你直接使用 Godot API 來以 C++ 開發專案,而 Unity 目前則沒辦法用 C++。這裡有個例子,可以把 Godot Engine 的編輯器想像成一個用 C++ 與 Godot API 寫出來的「遊戲」。

如果你想在 Godot 中使用 C++,你可能會想讀一下 以 C++ 開發 這頁。