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# 與 GDScript API 的差異,或者(重新)瀏覽按部就班教學的 腳本區段

C# is a high-level programming language developed by Microsoft. In Godot, it is implemented with the modern .NET runtime.

注意

目前使用 Godot 4 撰寫的 C# 專案尚無法匯出到網頁平台。如果你需要在網頁平台用 C#,請考慮改用 Godot 3。自 Godot 4.2 起已可匯出至 Android 與 iOS,但功能仍屬實驗性,且 有些限制

備註

本頁**不是**完整的 C# 語言教學。如果你還不熟悉 C# 的語法與功能,請參考 Microsoft C# 指南 或尋找其他合適的入門資源。

先決條件

Godot bundles the parts of .NET needed to run already-compiled games. However, Godot does not bundle the tools required to build and compile games, such as MSBuild and the C# compiler. These are included in the .NET SDK, and need to be installed separately.

總結來說,你必須安裝 .NET SDK 以及 支援 .NET 的 Godot 版本。

Download and install the latest stable version of the SDK from the .NET download page. Godot 4.5 requires .NET 8 or later, but exporting to Android requires .NET 9 or later.

重要

如果你使用的是 64 位元版本的 Godot,請務必安裝 64 位元的 SDK。

若你是從原始碼自行建置 Godot,請依照 使用 .NET 編譯 文件中的步驟啟用 .NET 支援。

設定外部編輯器

Godot 內建的腳本編輯器對 C# 的支援相當基本。建議改用外部 IDE 或編輯器,例如 Visual Studio CodeVisual Studio。它們提供自動完成、除錯等實用功能。要在 Godot 指定外部編輯器,請按 Editor → Editor Settings,往下捲到 Dotnet。在 Dotnet 底下點 Editor,選擇你偏好的外部編輯器。Godot 目前支援以下外部編輯器:

  • Visual Studio 2022

  • Visual Studio Code

  • MonoDevelop

  • Visual Studio for Mac

  • JetBrains Rider

有關如何設定外部編輯器,請參考以下說明:

JetBrains Rider

閱讀完「先決條件」後,即可下載並安裝 JetBrains Rider

在 Godot 的 編輯器 → 編輯器設定 選單:

  • Dotnet → Editor → External Editor 設為 JetBrains Rider

於 Rider:

  • MSBuild version 設為 .NET Core

  • 如果你使用 2024.2 之前版本的 Rider,請另外安裝 Godot support 擴充套件。新版 Rider 已內建此功能。

Visual Studio Code

閱讀完「先決條件」後,即可下載並安裝 Visual Studio Code (又稱 VS Code)。

在 Godot 的 編輯器 → 編輯器設定 選單:

  • Dotnet → Editor → External Editor 設為 Visual Studio Code

於 Visual Studio Code:

若要設定專案除錯,必須在 .vscode 資料夾內建立 tasks.jsonlaunch.json,並填入必要的設定。

以下為一個 launch.json 範例:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Play",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${env:GODOT4}",
            "args": [],
            "cwd": "${workspaceFolder}",
            "stopAtEntry": false,
        }
    ]
}

若要使這個啟動組態生效,你需要設定一個名為 GODOT4 的環境變數指向 Godot 執行檔,或直接將 program 欄位填入 Godot 執行檔的路徑。

以下為一個 tasks.json 範例:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}

現在,當你在 Visual Studio Code 啟動除錯器時,你的 Godot 專案就會執行。

Visual Studio(僅限 Windows)

下載並安裝最新版 Visual Studio。只要安裝時選對工作負載,Visual Studio 會自動包含所需 SDK,因此不需要額外手動安裝「先決條件」中的內容。

安裝 Visual Studio 時,請選擇以下工作負載:

  • .NET 桌面開發

在 Godot 的 編輯器 → 編輯器設定 選單:

  • Dotnet → Editor → External Editor 設為 Visual Studio

備註

如果看到「Unable to find package Godot.NET.Sdk」這類錯誤,表示 NuGet 設定有誤,需要修正。

解決 NuGet 設定檔的方法之一是重新產生它。在檔案總管中前往 %AppData%\NuGet,將 NuGet.Config 檔案重新命名或刪除。重新建置 Godot 專案時,該檔案會自動以預設值重建。

若要用 Visual Studio 除錯 C# 腳本,請開啟第一個 C# 腳本後產生的 .sln 檔。於 偵錯 選單中,進入專案的 偵錯屬性 。點擊 建立新設定檔 並選擇 可執行檔 。在 可執行檔 欄位選擇 Godot 編輯器支援 C# 版本的執行檔路徑,若已設好 GODOT4 環境變數,也可填 %GODOT4% 。此路徑必須是主 Godot 執行檔,不能用 console 版本。 工作目錄 填入單一點號 . (表示目前目錄)。勾選 啟用原生程式碼偵錯 。設定完成後即可關閉視窗,從偵錯設定檔下拉選單選擇剛建立的設定檔,點擊綠色開始按鈕,遊戲就會以除錯模式啟動。

建立 C# 腳本

當你成功設定好 Godot 的 C# 支援後,於場景節點的右鍵選單選擇 附加腳本 時應會出現下列選項:

../../../_images/attachcsharpscript.webp

請注意,儘管細節略有不同,大部分腳本概念在 C# 與 GDScript 之間是一致的。如果你剛接觸 Godot,建議先閱讀 為場景編寫腳本 相關教學。雖然有些文件頁面缺乏 C# 範例,大部分觀念都能直接從 GDScript 套用。

專案設定與工作流程

當你建立第一個 C# 腳本時,Godot 會自動初始化整個專案的 C# 專案檔案,包括產生 C# 解決方案(.sln)、專案檔(.csproj),以及一些工具相關檔案和資料夾(如 .godot/mono)。除了 .godot/mono 外,其餘都很重要,應納入版本控制。.godot 底下內容可安全加入版本控制忽略清單。有時排除問題時,刪除 .godot/mono 讓 Godot 重新產生會有幫助。

範例

以下是一個空白的 C# 腳本範例,並附有說明註解。

using Godot;

public partial class YourCustomClass : Node
{
    // Member variables here, example:
    private int _a = 2;
    private string _b = "textvar";

    public override void _Ready()
    {
        // Called every time the node is added to the scene.
        // Initialization here.
        GD.Print("Hello from C# to Godot :)");
    }

    public override void _Process(double delta)
    {
        // Called every frame. Delta is time since the last frame.
        // Update game logic here.
    }
}

如你所見,GDScript 中屬於全域作用域的函式(如 Godot 的 print 函式),在 C# 中則位於 Godot 命名空間內的靜態類別 GD。完整方法清單請參考類別參考文件:@GDScript@GlobalScope

備註

請注意,你要掛載到節點上的類別名稱必須與 .cs 檔案名稱相同,否則會出現下列錯誤:

"Cannot find class XXX for script res://XXX.cs"

C# 與 GDScript 的主要差異

C# API 採用 PascalCase (大駝峰式命名),而非 GDScript/C++ 的 snake_case (底線式命名)。大多數欄位與 getter/setter 都盡量轉換為屬性。整體而言,C# 的 Godot API 盡可能遵循慣用 C# 風格。

詳情請參閱 C# API 與 GDScript 的不同 頁面。

警告

每當你想在編輯器內看到新的匯出變數或訊號時,都必須重新建置專案組件。你可以點擊編輯器右上角的 建置 按鈕手動觸發建置。

../../../_images/build_dotnet.webp

若要套用「tool」腳本的變更,也必須重新建置專案組件。

目前注意事項與已知問題

由於 Godot 對 C# 的支援仍屬新穎,現階段仍有不少待完善之處。以下列出目前在 Godot 使用 C# 時需特別留意的重點問題。若有疑問,也可參閱官方的 .NET 問題追蹤

  • 雖然可以用 C# 撰寫編輯器外掛,但目前流程較為繁瑣。

  • 熱重載時,目前只有匯出變數的狀態會被保存與還原。

  • C# 腳本附加時,類別名稱必須與檔名相符。

  • 有些方法(如 Get()/Set()Call()/CallDeferred() 以及訊號連接用的 Connect())仍依賴 Godot 的 snake_case 命名。例如 CallDeferred("AddChild") 會失敗,因為 API 只接受原始的 add_child。但你可以自訂屬性或方法,不受此限。建議優先使用 PropertyNameMethodNameSignalName 等已公開的 StringName,這樣可避免多餘的 StringName 配置,也不用顧慮 snake_case。

自 Godot 4.0 起,.NET 專案可匯出至桌面平台(Linux、Windows、macOS)。其他平台的支援會於 4.x 未來版本陸續加入。

常見陷阱

你在嘗試修改部份 Godot 物件的屬性時(如變更 Node2D 的 X 座標)可能會遇到下列錯誤:

public partial class MyNode2D : Node2D
{
    public override void _Ready()
    {
        Position.X = 100.0f;
        // CS1612: Cannot modify the return value of 'Node2D.Position' because
        // it is not a variable.
    }
}

這是正常現象。C# 的結構(如 Vector2)在賦值時是複製,從屬性或索引子取得這類物件時,得到的是副本而非原物件。單獨改變副本的內容並不會改變原屬性,必須重新指定回去。

解法很簡單:先取出整個結構,修改所需值後,再把整個結構重新指定回屬性。

var newPosition = Position;
newPosition.X = 100.0f;
Position = newPosition;

自 C# 10 起,也可以在結構上使用 with 運算式,讓上述操作一行完成。

Position = Position with { X = 100.0f };

你可在 C# 語言參考 了解更多關於此錯誤的資訊。

Godot 的 C# 效能

也參考

關於 Godot 支援語言的效能比較,請參考 哪種程式語言最快?

大多數繼承自 GodotObject 的 C# 物件屬性(如 ControlCamera3D 等節點),在存取時都需與 Godot C++ 核心進行互操作(interop)呼叫。如果你需要重複存取或修改同一屬性,建議先存到區域變數再操作:

using Godot;

public partial class YourCustomClass : Node3D
{
    private void ExpensiveReposition()
    {
        for (var i = 0; i < 10; i++)
        {
            // Position is read and set 10 times which incurs native interop.
            // Furthermore the object is repositioned 10 times in 3D space which
            // takes additional time.
            Position += new Vector3(i, i);
        }
    }

    private void Reposition()
    {
        // A variable is used to avoid native interop for Position on every loop.
        var newPosition = Position;
        for (var i = 0; i < 10; i++)
        {
            newPosition += new Vector3(i, i);
        }
        // Setting Position only once avoids native interop and repositioning in 3D space.
        Position = newPosition;
    }
}

將原生陣列(如 byte[])或 string 傳遞給 Godot 的 C# API 時,會經過封送處理(marshalling),效能開銷較大。

string 隱式轉換為 NodePathStringName 時,會同時產生互操作與資料封送的效能損耗,因為字串需封送並傳給原生建構函式。

在 Godot 使用 NuGet 套件

你可以像一般 C# 專案一樣,在 Godot 中安裝並使用 NuGet 套件。多數 IDE 支援直接加入套件,也可手動於專案根目錄的 .csproj 檔案中加入套件參考:

    <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
    </ItemGroup>
    ...
</Project>

Godot automatically downloads and sets up newly added NuGet packages the next time it builds the project.

C# 程式碼效能剖析

你可使用下列工具分析受控(managed)程式碼的效能與記憶體:

  • JetBrains Rider,搭配 dotTrace/dotMemory 外掛。

  • 獨立版 JetBrains dotTrace/dotMemory。

  • Visual Studio。

JetBrains 工具與 Visual Studio 均可同時剖析受控與非受控程式碼,但僅支援 Windows。