Написание скриптов на 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");
}