Меж-языковые сценарии (скрипты)

Godot позволяет вам смешивать и сопоставлять языки сценариев в соответствии с вашими потребностями. Это означает, что один проект может определять узлы как в C#, так и в GDScript. На этой странице будут рассмотрены возможные взаимодействия между двумя узлами, написанными на разных языках.

Следующие два скрипта будут использоваться в качестве примера на этой странице.

extends Node

var str1 : String = "foo"
var str2 : String setget ,get_str2

func get_str2() -> String:
    return "foofoo"

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)

Создание экземпляров узлов

Если вы не используете узлы из дерева сцены, вы, вероятно, захотите создать экземпляры узлов непосредственно из кода.

Создание экземпляров узлов C# из GDScript

Использование C# из GDScript не требует особых усилий. После загрузки (см . Классы как ресурсы) сценарий может быть создан с помощью new().

var my_csharp_script = load("res://path_to_cs_file.cs")
var my_csharp_node = my_csharp_script.new()
print(my_csharp_node.str2) # barbar

Предупреждение

При создании сценариев`` .cs`` вы всегда должны помнить, что класс, который будет использовать Godot, называется так же, как и сам файл .cs. Если этот класс не существует в файле, вы увидите следующую ошибку: Invalid call. Nonexistent function `new` in base.

Например, MyCoolNode.cs должен содержать класс с именем MyCoolNode.

Вам также необходимо проверить, что ваш файл .cs указан в файле проекта .csproj. В противном случае произойдет та же ошибка.

Создание узлов GDScript из C#

Со стороны C# все работает точно также. После загрузки GDScript может быть создан с помощью GDScript.New().

GDScript MyGDScript = (GDScript) GD.Load("res://path_to_gd_file.gd");
Object myGDScriptNode = (Godot.Object) MyGDScript.New(); // This is a Godot.Object

Здесь мы используем Object, но вы можете использовать преобразование типов, как объяснено в Превращение типов и кастинг.

Доступ к полям

Доступ к полям C# из GDScript

Доступ к полям C# из GDScript прост, вам не о чем беспокоиться.

print(my_csharp_node.str1) # bar
my_csharp_node.str1 = "BAR"
print(my_csharp_node.str1) # BAR

print(my_csharp_node.str2) # barbar
# my_csharp_node.str2 = "BARBAR" # This line will hang and crash

Обратите внимание, что не имеет значения, определено ли поле как свойство или атрибут, но попытка установить значение для свойства, которое не определяет сеттер, приведет к ошибке.

Доступ к полям GDScript из C#

Поскольку C# статически типизирован, доступ к GDScript из C# немного более сложен, вам придется использовать Object.Get() и Object.Set(). Первый аргумент - это имя поля, к которому вы хотите получить доступ.

GD.Print(myGDScriptNode.Get("str1")); // foo
myGDScriptNode.Set("str1", "FOO");
GD.Print(myGDScriptNode.Get("str1")); // FOO

GD.Print(myGDScriptNode.Get("str2")); // foofoo
// myGDScriptNode.Set("str2", "FOOFOO"); // This line won't do anything

Имейте в виду, что при установке значения поля вы должны использовать только те типы, о которых знает сторона GDScript. По сути, вы хотите работать со встроенными типами, как описано в Основы GDScript, или с классами, расширяющими Object.

Методы вызова

Вызов C# методов из GDScript

Опять же, вызов методов C# из GDScript должен быть простым. Процесс маршаллинга приложит все усилия, чтобы привести ваши аргументы к сигнатурам функций. Если это невозможно, вы увидите следующую ошибку: Invalid call. Nonexistent function `FunctionName`.

my_csharp_node.PrintNodeName(self) # myGDScriptNode
# my_csharp_node.PrintNodeName() # This line will fail.

my_csharp_node.PrintNTimes("Hello there!", 2) # Hello there! Hello there!

my_csharp_node.PrintArray(["a", "b", "c"]) # a, b, c
my_csharp_node.PrintArray([1, 2, 3]) # 1, 2, 3

Вызов методов GDScript из C#

Для вызова методов GDScript из C# нужно использовать Object.Call(). Первый аргумент - имя метода, который вы хотите вызвать. Следующие аргументы будут переданы указанному методу.

myGDScriptNode.Call("print_node_name", this); // my_csharp_node
// myGDScriptNode.Call("print_node_name"); // This line will fail silently and won't error out.

myGDScriptNode.Call("print_n_times", "Hello there!", 2); // Hello there! Hello there!

// When dealing with functions taking a single array as arguments, we need to be careful.
// If we don't cast it into an object, the engine will treat each element of the array as a separate argument and the call will fail.
String[] arr = new String[] { "a", "b", "c" };
// myGDScriptNode.Call("print_array", arr); // This line will fail silently and won't error out.
myGDScriptNode.Call("print_array", (object)arr); // a, b, c
myGDScriptNode.Call("print_array", (object)new int[] { 1, 2, 3 }); // 1, 2, 3
// Note how the type of each array entry does not matter as long as it can be handled by the marshaller

Предупреждение

Как вы можете видеть, если первый аргумент вызываемого метода является массивом, вам нужно привести его как object. В противном случае каждый элемент вашего массива будет рассматриваться как один аргумент, и сигнатура функции не будет совпадать.

Наследование

Файл GDScript не может быть наследником сценария C#. Точно так же сценарий C# не может наследоваться от файла GDScript. Из-за сложности реализации это ограничение вряд ли удастся снять в будущем. См. эту проблему на GitHub для получения дополнительной информации.