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.

Багатомовні скрипти

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)

Вставка екземплярів (Instantiating) вузлів

Якщо ви не використовуєте вузли з дерева сцени, ви, ймовірно, захочете вставляти їх екземляри (instantiate) безпосередньо з коду.

Вставка екземплярів (Instantiating) вузлів 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 (Помилковий виклик. Не знайдено функцію new у базі).

Наприклад, MyCoolNode.cs повинен містити клас під назвою MyCoolNode.

Клас C# повинен отримати клас Godot, наприклад GodotObject. Інакше виникне та сама помилка.

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

Вставка екземплярів (Instantiating) вузлів GDScript на C#

З боку C# все працює так само. Після завантаження, GDScript може бути вставлений (instantiated) з 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#

As C# is statically typed, accessing GDScript from C# is a bit more convoluted. You will have to use GodotObject.Get() and GodotObject.Set(). The first argument is the name of the field you want to access.

// 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. По суті, ви хочете працювати з вбудованими типами, як описано Посилання на GDScript, або класах, що розширюють Object.

Методи виклику

Виклик методів C# з GDScript

Знову ж таки, виклик методів C# з GDScript повинен бути простим. Процес маршування зробить все можливе, щоб привести аргументи до відповідності підписів функцій. Якщо це неможливо, ви побачите наступне повідомлення про помилку: Invalid call. Nonexistent function `FunctionName` (Помилковий виклик. Не знайдено функцію 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.