Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

C# 基礎

前言

本頁提供了 C# 的簡介,包含 C# 為何以及如何在 Godot 中使用。之後,建議您也閱讀 如何使用特定功能C# 與 GDScript API 的比較 以及 (再次) 閱讀按部就班教學中的 腳本段落

C# 是由 Microsoft 開發的高級程式設計語言。在 Godot 中,它是使用 .NET 6.0 實作的。

注意

Projects written in C# using Godot 4 currently cannot be exported to the web platform. To use C# on the web platform, consider Godot 3 instead. Android and iOS platform support is available as of Godot 4.2, but is experimental and some limitations apply.

備註

本教學 不是 完整的 C# 語言教學。若您不熟悉 C# 的語法與功能,請參考 Microsoft C# 指南 或尋找其它合適的介紹。

先決條件

Godot 捆綁了運作已經編譯好的遊戲所需的 .NET 部分,但 Godot 不包括建構和編譯遊戲所需的 MSBuild 和 C# 編譯器等工具。這些工具包含在 .NET SDK 中,需要單獨安裝。

總之就是必須安裝 Visual Studio 或 Mono (依據作業系統而異) 並且 安裝有啟用 Mono 版本的 Godot。

.NET 下載頁面 下載並安裝SDK的最新穩定版本。

重要

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

必須使用有啟用 Mono 支援的 Godot 版本,請確保下載 Mono 版 的 Godot。若是從原始碼建置 Godot,請確保遵守 doc_compiling_with_mono 頁面中的步驟來啟用 Mono 支援。

設定外部編輯器

Godot 中的腳本編輯器僅對 C# 有最小限度的支援。建議使用外部 IDE 或編輯器,如 Visual Studio Code 或 MonoDevelop。這些編輯器有提供自動補全、除錯以及其他對 C# 實用的功能。要在 Godot 中選擇外部編輯器,請點擊 [編輯器] → [編輯器設定] 並向下滾動到 Mono 。在 Mono 中點擊 Editor 並選擇要使用的外部編輯器。Godot 目前支援下列外部編輯器:

  • Visual Studio 2019

  • Visual Studio Code

  • MonoDevelop

  • Mac 版 Visual Studio

  • JetBrains Rider

關於如何配置外部編輯器,請參見以下章節:

JetBrains Rider

閱讀完 "預備知識" 部分,就可以下載安裝 JetBrains Rider

在 Godot 的編輯器設定中:

  • Mono External Editor 設為 JetBrains Rider

Rider 中:

  • 設定 MSBuild version.NET Core

  • 安裝 Godot support 外掛。

Visual Studio Code

看完 "預備知識" 部分,就可以下載安裝 Visual Studio Code (又名 VS Code)。

在 Godot 的編輯器設定中:

  • Mono External Editor 設為 JetBrains Rider

Visual Studio Code

備註

如果你使用的是 Linux,需要安裝 Mono SDK 才能使用 C# 工具外掛程式。

為了配置一個用於除錯的專案,你需要在 .vscode 資料夾中擁有一個 tasks.jsonlaunch.json 檔,並進行必要的配置。一個範例配置可以在 這裡 找到。在 launch.json 檔中,請確保相關配置中的 program 參數指向你的 Godot 可執行檔,你可以通過將它更改為可執行檔的路徑或定義一個指向可執行檔的 GODOT4 環境變數來實作。現在,當你在 Visual Studio Code 中啟動除錯器時,你的 Godot 專案將會運作。

備註

還有一個 C# Tools for Godot 的 Visual Studio Code 擴充,使這一設定更加簡單並提供更多有用的工具。但它還沒有更新適配 Godot 4。

Visual Studio 或 VS Code

下載並安裝最新版本的 Visual Studio 。如果你選擇了正確的工作負載,Visual Studio 將包含所需的 SDK,所以你不需要手動安裝 "預先告知" 部分列出的內容。

Visual Studio 安裝須知

  • 編輯器開發

在 Godot 的編輯器設定中:

  • Mono External Editor 設為 JetBrains Rider

備註

如果你看到了類似“Unable to find package Godot.NET.Sdk”的錯誤,你的 NuGet 配置可能有問題,需要進行修復。

修復 NuGet 設定檔的簡單方法就是重新生成一個。在檔案瀏覽器視窗中前往 ''%AppData%NuGet''。將 ''NuGet.Config'' 檔案重命名或刪除。重新建立 Godot 專案時,就會自動用預設值建立該檔。

建立 C# 腳本

成功為 Godot 設定好 C# 後,應該可以在從場景中節點右鍵選單中選擇 [附加腳本] 時看到下列選項:

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

請注意,雖然某些功能不同,但使用 C# 撰寫腳本時大部分概念都一樣。若還不熟悉 Godot,則建議您先閱讀 為場景編寫腳本 中的教學。雖然文件中的某些部分還沒有 C# 範例,但大部分概念都很容易從 GDScript 轉過來。

專案設定與工作流程

建立第一個 C# 腳本後,Godot 會為目前的 Godot 專案初始化 C# 專案檔。包含產生 C# 解決方案 (.sln) 與專案檔 (.csproj)、以及一些公用檔案與資料夾 (.monoProperties/AssemblyInfo.cs)。這些檔案除了 .mono 之外都很重要,且應該被認可 (Commit) 至版本控制系統中。.mono 可以安全地新增到 VCS 中的忽略列表內,有時候可能會需要刪除 .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 函式,都在 Godot 命名空間中的 GD 類別內。要取得 GD 類別中所有方法的列表,請參考類別參照頁面中的 @GDScript@GlobalScope

備註

請記得,要附加到節點上的類別必須與 .cs 檔案的檔名相同。否則會得到下列錯誤且無法執行場景: 「Cannot find class XXX for script res://XXX.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# API 與 GDScript 的不同 一頁。

警告

You need to (re)build the project assemblies whenever you want to see new exported variables or signals in the editor. This build can be manually triggered by clicking the Build button in the top right corner of the editor.

../../../_images/build_dotnet1.webp

接著還需要重新建置專案組建,以套用「工具」腳本中的改動。

目前狀況與已知問題

由於 Godot 中的 C# 支援還很新,所以還有一些需要解決的問題。下表為在 Godot 中使用 C# 需要注意的幾個最重要的問題,另外也請參考一下官方的 Mono 問題追蹤器

  • 雖然還是可以寫編輯器外掛,但目前很複雜。

  • 除了匯出的變數以外,熱重載時狀態不會保存並重新載入。

  • 附加 C# 腳本時參照的類別名稱必須與檔名一致。

  • 有些方法,如 Get()/Set(), Call()/CallDeferred() 與訊號連接方法 Connect() 都還依賴 Godot 的 snake_case API 命名規範。所以使用如 CallDeferred("AddChild") 時,無法正常使用 AddChild ,因為 API 預期使用原本 snake_case 版的 add_child 。但依然可以使用自定屬性與方法而不受此限。

自 Godot 3.2.2 版起,匯出 Mono 專案支援桌面平台 (Linux, Windows 與 macOS), Android, HTML5 與 iOS。唯一還不支援的平台為 UWP。

註解

你可能會在嘗試修改 Godot 物件中的一些值時遇到以下錯誤,例如在嘗試改變一個 Node2D 的 X 座標時:

public partial class MyNode2D : Node2D
{
    public override _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 中的 C# 效能比起一些單純的 GDScript 情況還要快上 ~ 4 倍 。C++ 依然稍微快一點。實際情況還是依據使用方式而異。GDScript 一般來說對於普通的程式編寫來說已經夠快了,而 C# 雖然更快,但與 Godot 通訊時則需要耗費許多吃效能的封送處理。

大多數基於 GodotObject 的 Godot C# 物件(例如任何像 Control 這樣的 NodeCamera3D 這樣的 Node3D )的屬性,需要使用本地(互動操作)呼叫,因為它們與 Godot 的 C++ 核心進行通信。如果你需要在單個程式碼位置多次修改或讀取這些屬性的值,請考慮將其分配給本地變數:

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 需要進行資料封裝,這在性能上相對較昂貴。

string 隱式轉換為 NodePathStringName 會產生本地互動操作和資料封裝的成本,因為必須將 string 封裝並傳遞到相應的本地建構子。

在 Godot 中使用 NuGet 套件

可以在 Godot 中配合任意 C# 專案安裝與使用 NuGet 套件。許多 IDE 都支援直接新增套件,這些套件也可以通過在專案根目錄的 .csproj 檔內加上套件參照來手動新增:

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

從 Godot 3.2.3 開始,Godot 在下次建構專案時自動下載並設定新新增的 NuGet 包。

對 C# 程式進行程式碼剖析

以下工具可用於對託管程式碼進行性能和記憶體分析:

  • JetBrains Rider 配合 dotTrace/dotMemory 外掛程式。

  • 獨立版的 JetBrains dotTrace/dotMemory。

  • Visual Studio

使用 JetBrains tools 和 Visual Studio 可以同時對託管和非託管程式碼進行分析,但僅限於 Windows。