Características

Esta página provee un resumen acerca de las características comunmente utilizadas en C# y Godot y cómo son usadas.

Conversión de tipo y casting

C# es un lenguaje estáticamente tipado, por lo tanto, no puedes hacer lo siguiente:

var mySprite = GetNode("MySprite");
mySprite.SetFrame(0);

El método GetNode() retorna una instancia Node. Se debe convertir explícitamente al tipo derivado deseado, Sprite en este caso.

Para esto, hay varias opciones en C#.

Casting & Chequeo de Tipo

Lanza InvalidCastException si el valor retornado no puede ser convertido a Sprite. Se utiliza en lugar del operador as si se está seguro que no fallará.

Sprite mySprite = (Sprite)GetNode("MySprite");
mySprite.SetFrame(0);

Utilizando el operador AS

El operador as retorna null si el nodo no puede ser convertido a Sprite, y por esta razón no puede ser usado en tipos «valor».

Sprite mySprite = GetNode("MySprite") as Sprite;
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

Utilizando métodos genéricos

Los métodos genéricos se proveen para hacer la conversión de tipo transparente.

GetNode<T>() realiza un casting del nodo antes de retornarlo. Lanzará una InvalidCastException si el nodo no puede ser convertido al tipo deseado.

Sprite mySprite = GetNode<Sprite>("MySprite");
mySprite.SetFrame(0);

GetNodeOrNull<T>() usa el operador as y retornará null si el nodo no puede ser convertido al tipo deseado.

Sprite mySprite = GetNodeOrNull<Sprite>("MySprite");
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

Chequeo de tipo usando el operador IS

Para comprobar si un nodo puede ser convertido a Sprite, puedes usar el operador is. Este operador retorna false si el nodo no puede ser convertido a Sprite, de otro modo, retorna true.

if (GetNode("MySprite") is Sprite)
{
    // Yup, it's a sprite!
}

Para tipos avanzados de comprobaciones, puedes mirar Pattern Matching.

Señales en C#

Para ejemplos completos de C#, ver la sección Manipulando una señal en el tutorial paso a paso Scripting.

Una señal en C# se declara mediante el atributo [Signal] en un delegate.

[Signal]
delegate void MySignal();

[Signal]
delegate void MySignalWithArguments(string foo, int bar);

Esas señales pueden ser conectadas mediante el editor o por códibo con 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");
}

Las señales se emiten con el método EmitSignal.

public void SomeFunction()
{
    EmitSignal(nameof(MySignal));
    EmitSignal("MySignalWithArguments", "hello there", 28);
}

Tener en cuenta que se puede hacer referenciar a una señal con la palabra clave nameof (aplicado al delegate).

Es posible vincular valores al establecer una conexión pasando un objeto array.

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 });
}

Las señales soportan parámetros y valores vinculados de todos los tipos built-in y clases derivadas de Godot.Object. Consecuentemente, cualquier Node o Reference será compatible automaticamente, pero objetos de datos personalizados deberán extender de Godot.Object o alguna de sus subclases.

public class DataObject : Godot.Object
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

Finalmente, las señales pueden ser creadas llamando AddUserSinal, pero tener en cuenta que debe ser ejecutado antes de la utilización de dicha señal (con Connect o EmitSignal).

public void SomeFunction()
{
    AddUserSignal("MyOtherSignal");
    EmitSignal("MyOtherSignal");
}