Меж-языковые сценарии (скрипты)
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 для получения дополнительной информации.