Написание скриптов на C# в Godot. Особенности
На этой странице представлен обзор часто используемых функций C# и Godot, а также как они используются вместе.
Тип преобразования и приведение
C# - это язык со статической типизацией. Поэтому вы не можете делать следующее:
var mySprite = GetNode("MySprite") mySprite.SetFrame(0)
Метод GetNode()
возвращает экземпляр узла (Node
). Вы должны явно преобразовать его в требуемый производный тип, в данном случае Sprite
.
Для этого у в C# есть множество вариантов.
Преобразование и проверка типов
Выдает InvalidCastException
, если возвращаемый узел не может быть приведен к Sprite
. Вы бы использовали его вместо оператора as
, если уверены, что это не будет ошибкой.
Sprite mySprite = (Sprite)GetNode("MySprite"); mySprite.SetFrame(0);
Использование оператора as
Оператор as
возвращает null, если узел не может быть приведен к Sprite
, и по этой причине его нельзя использовать с типами значений.
Sprite mySprite = GetNode("MySprite") as Sprite; // Вызывайте SetFrame() только в том случае, если mySprite не равен null mySprite?.SetFrame(0);
Использование общих методов
Общие методы также предоставляются, чтобы сделать это преобразование типов прозрачным.
GetNode<T>()
преобразует узел перед его возвратом. Это вызовет InvalidCastException
, если узел не может быть приведен к желаемому типу.
Sprite mySprite = GetNode<Sprite>("MySprite"); mySprite.SetFrame(0);
GetNodeOrNull<T>()
использует оператор as
и возвращает null, если узел не может быть приведен к нужному типу.
Sprite mySprite = GetNodeOrNull<Sprite>("MySprite"); // Вызывайте SetFrame() только в том случае, если mySprite не равен null mySprite?.SetFrame(0);
Проверка типа с использованием оператора is
Чтобы проверить, может ли узел быть приведен к Sprite
, вы можете использовать оператор is
. Оператор is
возвращает false
, если узел не может быть приведен к Sprite
, в противном случае он возвращает true
.
if (GetNode("MySprite") is Sprite) { // Ура, это спрайт! }
Для более сложной проверки типов, вы можете посмотреть Pattern Matching.
Сигналы C#
Полный пример для C# см. в разделе Handling a signal в пошаговом руководстве Написание сценариев (скриптов)
Объявление сигнала в C# выполняется с помощью атрибута [Signal]
делегата.
[Signal] delegate void MySignal(); [Signal] delegate void MySignalWithArguments(string foo, int bar);
Эти сигналы могут быть подключены либо в редакторе, либо из кода с помощью Connect
.
public void MyCallback() { GD.Print("My callback!"); } public void MyCallbackWithArguments(string foo, int bar) { GD.Print("My callback with: ", foo, " and ", bar, "!"); } public void SomeFunction() { instance.Connect("MySignal", this, "MyCallback"); instance.Connect(nameof(MySignalWithArguments), this, "MyCallbackWithArguments"); }
Оправка сигналов осуществляется методом EmitSignal
.
public void SomeFunction() { EmitSignal(nameof(MySignal)); EmitSignal("MySignalWithArguments", "hello there", 28); }
Обратите внимание, что вы всегда можете ссылаться на имя сигнала с ключевым словом nameof
(применяется к самому делегату).
При установлении соединения можно связать значения, передав массив объектов.
public int Value { get; private set; } = 0; private void ModifyValue(int modifier) { Value += modifier; } public void SomeFunction() { var plusButton = (Button)GetNode("PlusButton"); var minusButton = (Button)GetNode("MinusButton"); plusButton.Connect("pressed", this, "ModifyValue", new object[] { 1 }); minusButton.Connect("pressed", this, "ModifyValue", new object[] { -1 }); }
Сигналы поддерживают параметры и связанные значения всех встроенных типов (built-in types) и классов, производных от Godot.Object. Следовательно, любой узел (Node
) или ссылка (Reference
) будут совместимы автоматически, но пользовательские объекты данных должны наследоваться от Godot.Object или одного из его подклассов.
public class DataObject : Godot.Object { public string Field1 { get; set; } public string Field2 { get; set; } }
Наконец, сигналы могут быть созданы путем вызова AddUserSignal
, но имейте в виду, что он должен выполняться перед любым использованием указанных сигналов (с Connect
или EmitSignal
).
public void SomeFunction() { AddUserSignal("MyOtherSignal"); EmitSignal("MyOtherSignal"); }