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.
Checking the stable version of the documentation...
Меж-языковые сценарии (скрипты)
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);
}
}
Создание экземпляров узлов
Если вы не используете узлы из дерева сцены, вы, вероятно, захотите создать экземпляры узлов непосредственно из кода.
Создание экземпляров узлов C# из GDScript
Использование C# из GDScript не требует особых усилий. После загрузки (см . Классы как ресурсы) сценарий может быть создан с помощью new().
var MyCSharpScript = load("res://Path/To/MyCSharpNode.cs")
var my_csharp_node = MyCSharpScript.new()
Предупреждение
При создании сценариев`` .cs`` вы всегда должны помнить, что класс, который будет использовать Godot, называется так же, как и сам файл .cs. Если этот класс не существует в файле, вы увидите следующую ошибку: Invalid call. Nonexistent function `new` in base.
Например, MyCoolNode.cs должен содержать класс с именем MyCoolNode.
Класс C# должен быть производным от класса Godot, например, GodotObject. В противном случае возникнет та же ошибка.
Вам также необходимо проверить, что ваш файл .cs указан в файле проекта .csproj. В противном случае произойдет та же ошибка.
Создание узлов GDScript из C#
Со стороны C# все работает точно также. После загрузки GDScript может быть создан с помощью GDScript.New().
var myGDScript = GD.Load<GDScript>("res://path/to/my_gd_script.gd");
var myGDScriptNode = (GodotObject)myGDScript.New(); // This is a GodotObject.
Здесь мы используем Object, но вы можете использовать преобразование типов, как объяснено в Преобразование и приведение типов.
Доступ к полям
Доступ к полям C# из GDScript
Доступ к полям C# из GDScript прост, вам не о чем беспокоиться.
# 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)
Доступ к полям GDScript из C#
Поскольку C# статически типизирован, доступ к GDScript из C# немного сложнее. Вам придётся использовать 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.
Методы вызова
Вызов C# методов из GDScript
Опять же, вызов методов C# из GDScript должен быть простым. Процесс маршаллинга приложит все усилия, чтобы привести ваши аргументы к сигнатурам функций. Если это невозможно, вы увидите следующую ошибку: 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])
Вызов методов GDScript из C#
Для вызова методов GDScript из C# необходимо использовать 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.
Подключение к сигналам
Подключение к сигналам C# из GDScript
Подключение к сигналу C# из GDScript аналогично подключению к сигналу, определенному в GDScript:
my_csharp_node.MySignal.connect(my_signal_handler)
my_csharp_node.MySignalWithParams.connect(my_signal_with_params_handler)
Подключение к сигналам GDScript из C#
Подключение к сигналу GDScript из C# работает только с методом 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 для получения дополнительной информации.