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.
Checking the stable version of the documentation...
Controller, Gamepads und Joysticks
Godot supports hundreds of controller models out of the box. Controllers are supported on Windows, macOS, Linux, Android, iOS, and HTML5.
Beachten Sie, dass speziellere Geräte wie Lenkräder, Ruderpedale und HOTAS weniger getestet sind und möglicherweise nicht immer wie erwartet funktionieren. Das Aufheben des Force-Feedbacks für diese Geräte ist ebenfalls noch nicht implementiert. Wenn Sie Zugang zu einem dieser Geräte haben, zögern Sie nicht, Bugs auf GitHub zu melden.
In dieser Anleitung lernen Sie:
Wie Sie Ihre Eingabelogik schreiben, um sowohl Tastatur- als auch Controllereingaben zu unterstützen.
Wie sich Controller anders verhalten können als Tastatur/Maus-Eingaben
Probleme mit Controllern in Godot beheben.
Unterstützung der Universaleingabe
Dank des Godot-Eingabeaktionssystems ist es möglich, sowohl Tastatur- als auch Controllereingaben zu unterstützen, ohne separate Codepfade schreiben zu müssen. Anstatt Tasten oder Controllertasten in Ihren Skripten fest zu kodieren, sollten Sie in den Projekteinstellungen Eingabeaktionen erstellen, die sich dann auf bestimmte Tasten- und Controllereingaben beziehen.
Eingabeaktionen werden auf der Seite Verwendung von InputEvent ausführlich erklärt.
Bemerkung
Im Gegensatz zur Tastatureingabe erfordert die Unterstützung von Maus- und Controllereingaben für eine Aktion (z. B. das Umsehen in einem Ego-Spiel) unterschiedliche Codepfade, da diese getrennt behandelt werden müssen.
Welche Input-Singleton-Methode sollte ich verwenden?
Es gibt 3 Möglichkeiten, analoge Eingaben zu erhalten:
Wenn Sie zwei Achsen haben (z.B. Joystick- oder WASD-Bewegung) und beide Achsen sich wie eine einzige Eingabe verhalten sollen, verwenden Sie
Input.get_vector()
:
# `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
# This handles deadzone in a correct way for most use cases.
# The resulting deadzone will have a circular shape as it generally should.
var velocity = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
# The line below is similar to `get_vector()`, except that it handles
# the deadzone in a less optimal way. The resulting deadzone will have
# a square-ish shape when it should ideally have a circular shape.
var velocity = Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")
).limit_length(1.0)
// `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
// This handles deadzone in a correct way for most use cases.
// The resulting deadzone will have a circular shape as it generally should.
Vector2 velocity = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
// The line below is similar to `get_vector()`, except that it handles
// the deadzone in a less optimal way. The resulting deadzone will have
// a square-ish shape when it should ideally have a circular shape.
Vector2 velocity = new Vector2(
Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"),
Input.GetActionStrength("move_back") - Input.GetActionStrength("move_forward")
).LimitLength(1.0);
Wenn Sie eine Achse haben, die in beide Richtungen gehen kann (wie z.B. ein Gashebel an einem Steuerknüppel), oder wenn Sie separate Achsen einzeln behandeln wollen, verwenden Sie
Input.get_axis()
:
# `walk` will be a floating-point number between `-1.0` and `1.0`.
var walk = Input.get_axis("move_left", "move_right")
# The line above is a shorter form of:
var walk = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
// `walk` will be a floating-point number between `-1.0` and `1.0`.
float walk = Input.GetAxis("move_left", "move_right");
// The line above is a shorter form of:
float walk = Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left");
Für andere Arten von analogen Eingängen, wie z.B. die Verarbeitung eines Triggers oder die gleichzeitige Verarbeitung einer Richtung, verwenden Sie
Input.get_action_strength()
:
# `strength` will be a floating-point number between `0.0` and `1.0`.
var strength = Input.get_action_strength("accelerate")
// `strength` will be a floating-point number between `0.0` and `1.0`.
float strength = Input.GetActionStrength("accelerate");
Für nicht-analoge digitale/boolean Eingaben (nur "gedrückt" oder "nicht gedrückt"-Werte), wie z.B. Controller-Buttons, Maustasten oder Tastaturtasten, verwenden Sie Input.is_action_pressed()
:
# `jumping` will be a boolean with a value of `true` or `false`.
var jumping = Input.is_action_pressed("jump")
// `jumping` will be a boolean with a value of `true` or `false`.
bool jumping = Input.IsActionPressed("jump");
Bemerkung
Wenn Sie wissen wollen, ob eine Eingabe im vorherigen Frame gerade eben gedrückt wurde, benutzen Sie Input.is_action_just_pressed()
anstelle von Input.is_action_pressed()
. Im Gegensatz zu Input.is_action_pressed()
, das true
zurückgibt, solange die Eingabe gehalten wird, gibt Input.is_action_just_pressed()
nur true
für einen Frame zurück, nachdem die Taste gedrückt wurde.
Vibrationen
Vibrationen (auch haptisches Feedback genannt) können verwendet werden, um das Gefühl eines Spiels zu verbessern. In einem Rennspiel können Sie zum Beispiel die Art der Oberfläche, auf der das Auto gerade fährt, durch Vibration vermitteln oder bei einem Unfall eine plötzliche Vibration erzeugen.
Verwenden Sie die Methode start_joy_vibration des Input-Singletons, um die Vibration eines Gamepads zu starten. Verwenden Sie stop_joy_vibration, um die Vibration vorzeitig zu beenden (nützlich, wenn beim Start keine Dauer angegeben wurde).
Auf mobilen Geräten können Sie auch vibrate_handheld verwenden, um das Gerät selbst vibrieren zu lassen (unabhängig vom Gamepad). Unter Android muss dazu die Berechtigung VIBRATE
in der Android-Exportvorgabe aktiviert werden, bevor das Projekt exportiert wird.
Bemerkung
Vibrationen können für manche Spieler unangenehm sein. Stellen Sie sicher, dass es einen Schieberegler im Spiel gibt, um die Vibration zu deaktivieren oder ihre Intensität zu verringern.
Unterschiede zwischen Tastatur/Maus und Controller-Eingabe
Wenn Sie es gewohnt sind, mit Tastatur- und Mauseingaben umzugehen, werden Sie vielleicht überrascht sein, wie Controller mit bestimmten Situationen umgehen.
Totzone
Im Gegensatz zu Tastaturen und Mäusen verfügen Controller über Achsen mit analogem Eingang. Der Vorteil von Analogeingängen ist, dass sie zusätzliche Flexibilität für Aktionen bieten. Im Gegensatz zu digitalen Eingängen, die nur die Stärken 0.0
und 1.0
liefern können, kann ein analoger Eingang jede Stärke zwischen 0.0
und 1.0
liefern. Der Nachteil ist, dass ohne ein Totzonen-System die Stärke einer analogen Achse niemals gleich 0.0
sein wird, aufgrund der Art, wie der Controller physikalisch aufgebaut ist. Stattdessen wird sie bei einem niedrigen Wert wie 0.062
verweilen. Dieses Phänomen ist als Drifting bekannt und kann bei alten oder defekten Controllern stärker auffallen.
Nehmen wir ein Rennspiel als Beispiel aus der Praxis. Dank der analogen Eingaben können wir das Auto langsam in die eine oder andere Richtung lenken. Ohne ein Totzonen-System würde das Auto jedoch von selbst langsam lenken, auch wenn der Spieler den Joystick nicht berührt. Das liegt daran, dass die Stärke der Richtungsachse nicht gleich 0.0
ist, wenn wir es erwarten. Da wir nicht wollen, dass unser Auto in diesem Fall von selbst lenkt, definieren wir einen "Totzonen"-Wert von 0.2
, der alle Eingaben ignoriert, deren Stärke kleiner als 0.2
ist. Ein idealer Wert für die Totzone ist hoch genug, um die Eingaben zu ignorieren, die durch das Abdriften des Joysticks verursacht werden, aber niedrig genug, um die tatsächlichen Eingaben des Spielers nicht zu ignorieren.
Godot verfügt über ein eingebautes Totzonen-System, um dieses Problem zu lösen. Der Standardwert ist 0.5
, aber Sie können ihn für jede Aktion auf der Input Map-Tab der Projekteinstellungen anpassen. Für Input.get_vector()
kann die Totzone als optionaler fünfter Parameter angegeben werden. Wenn er nicht angegeben wird, wird der durchschnittliche Wert der Totzone aus allen Aktionen im Vektor berechnet.
"Echo"-Events
Im Gegensatz zur Tastatureingabe erzeugt das Drücken einer Controllertaste, z.B. des D-Pads, keine wiederholten Eingabe-Events in festen Intervallen (auch als "Echo"-Ereignisse bekannt). Das liegt daran, dass das Betriebssystem niemals "Echo"-Events für Controllereingaben sendet.
Wenn Sie möchten, dass Controller-Buttons Echo-Events senden, müssen Sie InputEvent-Objekte per Code generieren und sie mit Input.parse_input_event() in regelmäßigen Abständen auslesen. Dies kann mit Hilfe eines Timer-Nodes erreicht werden.
Fenster-Fokus
Im Gegensatz zu Tastatureingaben können Controllereingaben von allen Fenstern des Betriebssystems gesehen werden, auch von nicht fokussierten Fenstern.
Dies ist zwar für die Split-Screen-Funktionalität von Drittanbietern nützlich, kann aber auch nachteilige Auswirkungen haben. Spieler können versehentlich Controller-Eingaben an das laufende Projekt senden, während sie mit einem anderen Fenster interagieren.
Falls Sie Events ignorieren wollen, wenn das Projektfenster nicht fokussiert ist, müssen Sie einen autoload mit dem Namen Focus
mit folgendem Skript erstellen und es benutzen, um alle Ihre Inputs zu überprüfen:
# Focus.gd
extends Node
var focused := true
func _notification(what: int) -> void:
match what:
NOTIFICATION_APPLICATION_FOCUS_OUT:
focused = false
NOTIFICATION_APPLICATION_FOCUS_IN:
focused = true
func input_is_action_pressed(action: StringName) -> bool:
if focused:
return Input.is_action_pressed(action)
return false
func event_is_action_pressed(event: InputEvent, action: StringName) -> bool:
if focused:
return event.is_action_pressed(action)
return false
Dann verwenden Sie statt Input.is_action_pressed(action)
die Funktion Focus.input_is_action_pressed(action)
, wobei action
der Name der Eingabeaktion ist. Anstelle von event.is_action_pressed(action)
verwenden Sie Focus.event_is_action_pressed(event, action)
, wobei event
eine InputEvent-Referenz und action
der Name der Eingabeaktion ist.
Verhindern des Energiesparmodus
Im Gegensatz zu Tastatur- und Mauseingaben verhindern Controller-Eingaben nicht den Ruhezustand und Energiesparmodi (z. B. das Ausschalten des Bildschirms nach einer bestimmten Zeitspanne).
Um dem entgegenzuwirken, aktiviert Godot standardmäßig die Energiesparvermeidung, wenn ein Projekt ausgeführt wird. Wenn Sie feststellen, dass das System seinen Bildschirm ausschaltet, wenn Sie mit einem Gamepad spielen, überprüfen Sie den Wert von Anzeige > Fenster > Energiesparen > Bildschirm eingeschaltet lassen in den Projekteinstellungen.
Unter Linux setzt die Energiesparvermeidung voraus, dass die Engine in der Lage ist, D-Bus zu verwenden. Prüfen Sie, ob D-Bus installiert und erreichbar ist, wenn Sie das Projekt in einem Flatpak ausführen, da Sandboxing-Einschränkungen dies standardmäßig unmöglich machen können.
Fehlersuche
Siehe auch
Sie können eine Liste der bekannten Issues mit der Controller-Unterstützung auf GitHub einsehen.
Mein Controller wird von Godot nicht erkannt.
Überprüfen Sie zunächst, ob Ihr Controller von anderen Anwendungen erkannt wird. Sie können die Website Gamepad Tester verwenden, um zu überprüfen, ob Ihr Controller erkannt wird.
Unter Windows unterstützt Godot nur bis zu 4 Controller gleichzeitig. Das liegt daran, dass Godot die XInput-API verwendet, die nur 4 Controller gleichzeitig unterstützen kann. Zusätzliche Controller über diese Grenze hinaus werden von Godot ignoriert.
Mein Controller funktioniert auf einer bestimmten Plattform, aber nicht auf einer anderen Plattform.
Linux
Wenn Sie eine selbst kompilierte Engine-Binärdatei verwenden, stellen Sie sicher, dass sie mit udev-Unterstützung kompiliert wurde. Diese ist standardmäßig aktiviert, aber es ist möglich, die udev-Unterstützung zu deaktivieren, indem man udev=no
auf der SCons-Kommandozeile angibt. Wenn Sie eine Engine-Binärdatei verwenden, die von einer Linux-Distribution geliefert wird, überprüfen Sie, ob sie mit udev-Unterstützung kompiliert wurde.
Controller können auch ohne udev-Unterstützung funktionieren, aber es ist weniger zuverlässig, da regelmäßiges Polling verwendet werden muss, um zu überprüfen, ob die Controller während des Spiels angeschlossen oder getrennt werden (Hotplugging).
HTML5
Die Unterstützung für Controller bei HTML5-Spielen ist im Vergleich zu "nativen" Plattformen oft weniger zuverlässig. Die Qualität der Controller-Unterstützung ist von Browser zu Browser sehr unterschiedlich. Daher müssen Sie Ihre Spieler möglicherweise anweisen, einen anderen Browser zu verwenden, wenn sie ihren Controller nicht zum Laufen bringen können.