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.

C# 語言特性

本頁概述 C# 和 Godot 常用的特性,以及如何搭配使用。

型別轉換與轉型

C# 是靜態型別語言,因此,無法執行如下操作:

var mySprite = GetNode("MySprite");
mySprite.SetFrame(0);

GetNode() 方法會回傳一個 Node 實例。你必須明確將其轉型為你需要的衍生型別,例如本例中的 Sprite2D。

針對這種情況,C# 提供了多種作法。

轉型與型別檢查

若回傳的節點無法轉型為 Sprite2D,這種方式會拋出 InvalidCastException。當你很確定不會失敗時,可以用這種方式取代 as 運算子。

Sprite2D mySprite = (Sprite2D)GetNode("MySprite");
mySprite.SetFrame(0);

使用 as 運算子

as 運算子在無法將節點轉型為 Sprite2D 時會回傳 null,因此不能用於值型別。

Sprite2D mySprite = GetNode("MySprite") as Sprite2D;
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

使用泛型方法

也可以使用泛型方法來讓型別轉換變得更簡單直觀。

GetNode<T>() 會在回傳前將節點轉型。如果節點無法轉型為所需型別,會拋出 InvalidCastException。

Sprite2D mySprite = GetNode<Sprite2D>("MySprite");
mySprite.SetFrame(0);

GetNodeOrNull<T>() 會使用 as 運算子,若節點無法轉型為所需型別時會回傳 null。

Sprite2D mySprite = GetNodeOrNull<Sprite2D>("MySprite");
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

使用 is 運算子進行型別檢查

To check if the node can be cast to Sprite2D, you can use the is operator. The is operator returns false if the node cannot be cast to Sprite2D, otherwise it returns true. Note that when the is operator is used against null the result is always going to be false.

if (GetNode("MySprite") is Sprite2D)
{
    // Yup, it's a Sprite2D!
}

if (null is Sprite2D)
{
    // This block can never happen.
}

若 is 運算子回傳 true,你也可以宣告新變數來儲存轉型結果。

if (GetNode("MySprite") is Sprite2D mySprite)
{
    // The mySprite variable only exists inside this block, and it's never null.
    mySprite.SetFrame(0);
}

如需進階型別檢查,可參考 模式比對。

前置處理器定義

Godot 提供一系列定義,可讓你根據編譯目標環境調整 C# 程式碼。

範例

例如,你可以依據平台切換程式碼:

    public override void _Ready()
    {
#if (GODOT_MOBILE || GODOT_WEB)
        // Use simple objects when running on less powerful systems.
        SpawnSimpleObjects();
#else
        SpawnComplexObjects();
#endif
    }

或是偵測你的程式碼目前運行於哪個引擎,這對製作跨引擎函式庫很有幫助:

    public void MyPlatformPrinter()
    {
#if GODOT
        GD.Print("This is Godot.");
#elif UNITY_5_3_OR_NEWER
        print("This is Unity.");
#else
        throw new NotSupportedException("Only Godot and Unity are supported.");
#endif
    }

你也可以撰寫腳本,同時支援多個 Godot 版本,並運用僅部分版本支援的功能:

    public void UseCoolFeature()
    {
#if GODOT4_3_OR_GREATER || GODOT4_2_2_OR_GREATER
        // Use CoolFeature, that was added to Godot in 4.3 and cherry-picked into 4.2.2, here.
#else
        // Use a workaround for the absence of CoolFeature here.
#endif
    }

完整定義列表

  • GODOT 會在所有 Godot 專案中被定義。

  • TOOLS 會在使用 Debug 組態(編輯器與編輯器執行)建構時被定義。

  • 當 GodotFloat64 屬性設為 true 時,會定義 GODOT_REAL_T_IS_DOUBLE。

  • 根據作業系統,會定義 GODOT_LINUXBSD、GODOT_WINDOWS、GODOT_OSX、GODOT_ANDROID、GODOT_IOS 或 GODOT_WEB 其中之一。這些名稱未來可能變動。這些名稱源自 OS 單例的 get_name() 方法,但該方法回傳的所有作業系統,不一定都支援 Godot .NET 執行。

  • GODOTX、GODOTX_Y、GODOTX_Y_Z、GODOTx_OR_GREATER、GODOTX_y_OR_GREATER 以及 GODOTX_Y_z_OR_GREATER,其中 X、Y、Z 分別代表目前 Godot 的主、次、修正版號,x、y、z 則代表從 0 到該欄位目前版本號的所有值。

    備註

    這些定義自 Godot 4.0.4 與 4.1 之後才出現。舊版 Godot 不會有這些版本定義。

    舉例來說:Godot 4.0.5 會定義 GODOT4、GODOT4_OR_GREATER、GODOT4_0、GODOT4_0_OR_GREATER、GODOT4_0_5、GODOT4_0_4_OR_GREATER 和 GODOT4_0_5_OR_GREATER。Godot 4.3.2 會定義 GODOT4、GODOT4_OR_GREATER、GODOT4_3、GODOT4_0_OR_GREATER、GODOT4_1_OR_GREATER、GODOT4_2_OR_GREATER、GODOT4_3_OR_GREATER、GODOT4_3_2、GODOT4_3_0_OR_GREATER、GODOT4_3_1_OR_GREATER 與 GODOT4_3_2_OR_GREATER。

匯出時,根據匯出目標還會有以下定義:

  • 根據平台類型,會定義 GODOT_PC、GODOT_MOBILE 或 GODOT_WEB 其中之一。

  • 根據平台,會定義 GODOT_WINDOWS、GODOT_LINUXBSD、GODOT_MACOS、GODOT_ANDROID、GODOT_IOS 或 GODOT_WEB 其中之一。

欲查看範例專案,請參考作業系統測試範例: https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test