Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

C#-Signale

Eine ausführliche Erklärung von Signalen im Allgemeinen finden Sie im Abschnitt Signale nutzen in der Schritt-für-Schritt-Anleitung.

Während es immer noch möglich ist, Signale durch die Connect/Disconnect-API zu verwenden, gibt uns C# einen idiomatischeren Weg, das Observer-Pattern zu implementieren.

Signale als C#-Events

Um mehr Typsicherheit zu bieten, sind Godot-Signale auch alle über Events verfügbar. Sie können diese Events, wie jedes andere Events, mit den Operatoren += und -= behandeln.

Timer myTimer = GetNode<Timer>("Timer");
myTimer.Timeout += () => GD.Print("Timeout!");

Außerdem können Sie immer auf Signalnamen zugreifen, die mit einem Node-Typ durch seine eingebettete SignalName-Klasse verbunden sind. Dies ist nützlich, wenn Sie zum Beispiel auf ein Signal warten wollen (siehe Schlüsselwort await).

await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);

Warnung

While all engine signals connected as events are automatically disconnected when nodes are freed, custom signals aren't. Meaning that: you will need to manually disconnect (using -=) all the custom signals you connected as C# events (using +=).

Benutzerdefinierte Signale als C#-Ereignisse

Um ein benutzerdefiniertes Ereignis in Ihrem C#-Skript zu deklarieren, verwenden Sie das [Signal]-Attribut für einen öffentlichen Delegate-Typ. Beachten Sie, dass der Name dieses Delegate mit EventHandler enden muss.

[Signal]
public delegate void MySignalEventHandler();

[Signal]
public delegate void MySignalWithArgumentEventHandler(string myString);

Sobald dies geschehen ist, wird Godot die entsprechenden Events automatisch hinter den Kulissen erstellen. Sie können diese Events dann wie jedes andere Godot-Signal verwenden. Beachten Sie, dass die Events mit dem Namen Ihres Delegate ohne den abschließenden Teil EventHandler benannt werden.

public override void _Ready()
{
    MySignal += () => GD.Print("Hello!");
    MySignalWithArgument += SayHelloTo;
}

private void SayHelloTo(string name)
{
    GD.Print($"Hello {name}!");
}

Warnung

Wenn Sie eine Verbindung zu diesen Signalen im Editor herstellen wollen, müssen Sie das Projekt (neu) bauen, damit sie angezeigt werden.

Klicken Sie dazu auf die Schaltfläche Build in der oberen rechten Ecke des Editors.

Aussenden von Signalen

Um Signale auszusenden, verwenden Sie die Methode EmitSignal. Beachten Sie, dass, wie bei den von der Engine definierten Signalen, Ihre eigenen Signalnamen unter der eingebetteten Klasse SignalName aufgeführt werden.

public void MyMethodEmittingSignals()
{
    EmitSignal(SignalName.MySignal);
    EmitSignal(SignalName.MySignalWithArgument, "World");
}

Im Gegensatz zu anderen C#-Ereignissen können Sie Invoke nicht verwenden, um Events auszulösen, die an Godot-Signale gebunden sind.

Signale unterstützen Argumente eines beliebigen Variant-kompatiblen Typs.

Consequently, any Node or RefCounted will be compatible automatically, but custom data objects will need to inherit from GodotObject or one of its subclasses.

using Godot;

public partial class DataObject : GodotObject
{
    public string MyFirstString { get; set; }
    public string MySecondString { get; set; }
}

Gebundene Werte

Manchmal möchten Sie Werte an ein Signal binden, wenn die Verbindung hergestellt wird, anstatt (oder zusätzlich) wenn das Signal ausgesendet wird. Zu diesem Zweck können Sie eine anonyme Funktion wie im folgenden Beispiel verwenden.

Hier nimmt das Button.Pressed Signal kein Argument an. Aber wir wollen denselben ModifyValue für die "Plus"- und "Minus"-Buttons verwenden. Also binden wir den Modifikatorwert zu dem Zeitpunkt, zu dem wir die Signale verbinden.

public int Value { get; private set; } = 1;

public override void _Ready()
{
    Button plusButton = GetNode<Button>("PlusButton");
    plusButton.Pressed += () => ModifyValue(1);

    Button minusButton = GetNode<Button>("MinusButton");
    minusButton.Pressed += () => ModifyValue(-1);
}

private void ModifyValue(int modifier)
{
    Value += modifier;
}

Signalerzeugung zur Laufzeit

Schließlich können Sie eigene Signale direkt während des Spiels erstellen. Verwenden Sie dazu die Methode AddUserSignal. Seien Sie sich bewusst, dass diese Methode ausgeführt werden sollte, bevor Sie die Signale benutzen (entweder um sich mit ihnen zu verbinden oder um sie auszusenden). Beachten Sie auch, dass Signale, die auf diese Weise erstellt werden, nicht durch die eingebettete Klasse SignalName sichtbar sind.

public override void _Ready()
{
    AddUserSignal("MyCustomSignal");
    EmitSignal("MyCustomSignal");
}