跨語言腳本撰寫
Godot 允許你根據需求混用各種腳本語言。這代表單一專案內可以同時以 C# 與 GDScript 定義節點。本頁將說明用不同語言撰寫的兩個節點間的各種互動方式。
本頁將持續以以下兩個腳本作為範例參考。
extends Node
var my_property: String = "my gdscript value":
get:
return my_property
set(value):
my_property = value
signal my_signal
signal my_signal_with_params(msg: String, n: int)
func print_node_name(node: Node) -> void:
print(node.get_name())
func print_array(arr: Array) -> void:
for element in arr:
print(element)
func print_n_times(msg: String, n: int) -> void:
for i in range(n):
print(msg)
func my_signal_handler():
print("The signal handler was called!")
func my_signal_with_params_handler(msg: String, n: int):
print_n_times(msg, n)
using Godot;
public partial class MyCSharpNode : Node
{
public string MyProperty { get; set; } = "my c# value";
[Signal] public delegate void MySignalEventHandler();
[Signal] public delegate void MySignalWithParamsEventHandler(string msg, int n);
public void PrintNodeName(Node node)
{
GD.Print(node.Name);
}
public void PrintArray(string[] arr)
{
foreach (string element in arr)
{
GD.Print(element);
}
}
public void PrintNTimes(string msg, int n)
{
for (int i = 0; i < n; ++i)
{
GD.Print(msg);
}
}
public void MySignalHandler()
{
GD.Print("The signal handler was called!");
}
public void MySignalWithParamsHandler(string msg, int n)
{
PrintNTimes(msg, n);
}
}
實例化節點
如果沒有從場景樹取得節點,你大多會直接在程式碼中實例化節點。
從 GDScript 實例化 C# 節點
從 GDScript 使用 C# 並不麻煩。腳本載入後(參見 以類別當作資源),即可直接用 new() 來實例化。
var MyCSharpScript = load("res://Path/To/MyCSharpNode.cs")
var my_csharp_node = MyCSharpScript.new()
警告
建立 .cs 腳本時,請務必確認類別名稱與 .cs 檔案名稱一致。若檔案內沒有同名類別,會出現這個錯誤:「Invalid call. Nonexistent function new in base」。
例如,MyCoolNode.cs 應包含名為 MyCoolNode 的類別。
C# 類別必須繼承自 Godot 的類別,例如 GodotObject。否則也會發生相同的錯誤。
你還要確認 .cs 檔案已經在專案的 .csproj 檔案中被正確引用。否則也會出現相同的錯誤。
從 C# 實例化 GDScript 節點
在 C# 端,流程也是一樣。腳本載入後,可以用 GDScript.New() 來實例化 GDScript。
var myGDScript = GD.Load<GDScript>("res://path/to/my_gd_script.gd");
var myGDScriptNode = (GodotObject)myGDScript.New(); // This is a GodotObject.
存取欄位
從 GDScript 存取 C# 欄位
從 GDScript 存取 C# 欄位非常直接,無需額外注意事項。
# Output: "my c# value".
print(my_csharp_node.MyProperty)
my_csharp_node.MyProperty = "MY C# VALUE"
# Output: "MY C# VALUE".
print(my_csharp_node.MyProperty)
從 C# 存取 GDScript 欄位
由於 C# 為靜態型別語言,從 C# 存取 GDScript 欄位會稍微麻煩些。你需要使用 GodotObject.Get() 及 GodotObject.Set()。第一個參數為欲存取的欄位名稱。
// Output: "my gdscript value".
GD.Print(myGDScriptNode.Get("my_property"));
myGDScriptNode.Set("my_property", "MY GDSCRIPT VALUE");
// Output: "MY GDSCRIPT VALUE".
GD.Print(myGDScriptNode.Get("my_property"));
請記得,在設定欄位值時只能使用 GDScript 端所認得的型別。基本上,你應使用 內建型別 中描述的內建型別,或是繼承自 Object 的類別。
呼叫方法
從 GDScript 呼叫 C# 方法
同樣地,從 GDScript 呼叫 C# 方法也很直覺。資料封送處理會盡力將參數轉換為正確的類型以符合函式簽名。若無法轉換,會顯示錯誤:「Invalid call. Nonexistent function FunctionName」。
# Output: "my_gd_script_node" (or name of node where this code is placed).
my_csharp_node.PrintNodeName(self)
# This line will fail.
# my_csharp_node.PrintNodeName()
# Outputs "Hello there!" twice, once per line.
my_csharp_node.PrintNTimes("Hello there!", 2)
# Output: "a", "b", "c" (one per line).
my_csharp_node.PrintArray(["a", "b", "c"])
# Output: "1", "2", "3" (one per line).
my_csharp_node.PrintArray([1, 2, 3])
從 C# 呼叫 GDScript 方法
要從 C# 呼叫 GDScript 方法,需使用 GodotObject.Call()。第一個參數為方法名稱,其餘參數則依序傳入該方法。
// Output: "MyCSharpNode" (or name of node where this code is placed).
myGDScriptNode.Call("print_node_name", this);
// This line will fail silently and won't error out.
// myGDScriptNode.Call("print_node_name");
// Outputs "Hello there!" twice, once per line.
myGDScriptNode.Call("print_n_times", "Hello there!", 2);
string[] arr = ["a", "b", "c"];
// Output: "a", "b", "c" (one per line).
myGDScriptNode.Call("print_array", arr);
// Output: "1", "2", "3" (one per line).
myGDScriptNode.Call("print_array", new int[] { 1, 2, 3 });
// Note how the type of each array entry does not matter
// as long as it can be handled by the marshaller.
連接訊號
從 GDScript 連接到 C# 訊號
從 GDScript 連接到 C# 訊號的方式,與連接至 GDScript 定義的訊號完全相同:
my_csharp_node.MySignal.connect(my_signal_handler)
my_csharp_node.MySignalWithParams.connect(my_signal_with_params_handler)
從 C# 連接到 GDScript 訊號
從 C# 連接到 GDScript 訊號時,只能用 Connect 方法,因為 GDScript 定義的訊號沒有對應的 C# 靜態型別:
myGDScriptNode.Connect("my_signal", Callable.From(MySignalHandler));
myGDScriptNode.Connect("my_signal_with_params", Callable.From<string, int>(MySignalWithParamsHandler));
繼承
GDScript 檔案不能繼承自 C# 腳本,同樣地,C# 腳本也無法繼承 GDScript 檔案。由於實作上過於複雜,這項限制未來也不太可能解除。詳情請參閱 這個 GitHub issue。