Enhanced Input
Enhanced Input ist ein von Epic Games entwickeltes Plugin, das wir in „Parrot“ verwenden. Wenn du die neueste Version der Unreal Engine 5 verwendest, sollte es standardmäßig aktiviert sein. Du kannst sicherstellen, ob es aktiviert ist, indem du zu Bearbeiten > Plugins gehst und das Kontrollkästchen aktivierst.
Enhanced Input ersetzt das Standard-Inputsystem von Unreal Engine und ist der Standard für komplexes Input Handling oder Laufzeit-Control-Remapping. Die offizielle Dokumentation von Epic Games bietet einen ausgezeichneten Überblick über das System und zeigt, wie du deine Inputgeräte einrichtest.
Grundlegende Konzepte
Wie in der offiziellen Dokumentation beschrieben, sind dies die wichtigsten Konzepte von Enhanced Input, die du verstehen musst:
Input-Aktionen
Input-Mapping-Kontexte (IMCs)
Input-Modifikatoren
Input-Trigger
Wenn du mit dem neuen Inputsystem von Unity gearbeitet hast, sollten dir diese Konzepte vertraut sein.
Input-Aktionen kann man sich am besten als das vorstellen, was die Aktion, die im Spiel ausgeführt wird, in einem bestimmten Kontext des Spiels bewirkt. Wenn dein Charakter zum Beispiel in einem Auto sitzt, möchtest du die Aktionen „Beschleunigen“ und „Bremsen“ haben.
Input-Mapping-Kontexte funktionieren auch mit diesem Beispiel. Wenn der Spieler in das Auto ein- oder aussteigt, musst du vielleicht die Funktion bestimmter Tasten oder Gamepad-Schaltflächen ändern.
Input Trigger verhindern, dass Aktionen ausgelöst werden, wenn nicht alle Triggerbedingungen erfüllt sind. Du möchtest zum Beispiel, dass der Spieler eine Taste eine bestimmte Zeit lang gedrückt hält, um eine Aktion auszulösen.
Input-Modifikatoren ändern den Wert des Inputs selbst. Tote Zonen sind ein gängiger Input-Modifikator, der verwendet wird, um rohe Input-Werte abzuschwächen. Enhanced Input löst mit ein paar Einstellungen all diese Probleme für dich.
Schauen wir uns ein Beispiel in „Parrot“ an. Unter Content/Input/Gameplay findest du einen Ordner Actions und eine Asset-Datei IMC_Gameplay. Suche im Ordner Actions das Asset IA_Jump.
Der Werttyp ist hier Digital (bool), was den Output-Typ dieser Aktion angibt. Bei den Triggern gibt es die folgenden Typen:
Pressed (Wurde gedrückt)
Released (Wurde losgelassen)
Wenn man sich diese Input-Aktion anschaut, kann man erkennen, dass jede Taste oder jeder Button durch einen Druck ausgelöst werden muss und einen boolschen Output-Zustand hat. Das Loslassen der Taste löst das Ende der Aktion aus. Ein weiteres wichtiges Detail ist, dass sowohl Trigger als auch Modifikatoren durch einen Input-Mapping-Kontext außer Kraft gesetzt werden können. Werfen wir einen Blick auf den Gameplay-Input-Mapping-Kontext, um das Überschreiben von Modifikatoren in der Praxis zu sehen.
IA_MoveAxis hat keinen Trigger, so dass der Wert des Gamepads Left Thumbstick X-Axis hier sofort gelesen wird, wenn eine Änderung erkannt wird. Zur Abschwächung der rohen Input-Werte verwenden wir einen Totzonen-Modifikator, um die oberen und unteren Input-Grenzen festzulegen.
Ein Beispiel, bei dem wir im IMC keine Überschreibung vorsehen, ist das Jump-Mapping.
Hier wird deutlich, dass der Trigger von der Input-Aktion selbst kommt, so dass es nicht notwendig ist, einen Trigger für das Mapping zu definieren. Die Einstellungen werden auch von der Aktion geerbt, aber das kannst du vorerst ignorieren, da es im Abschnitt über das Remapping behandelt wird.
Enhanced Input Event-Listeners
Nachdem du nun deine Assets eingerichtet hast, musst du noch einige Einstellungen für die Verwendung zur Laufzeit vornehmen. In „Parrot“ binden wir uns an das Enhanced Input Local Player Subsystem, um unsere Event-Listener im BP_„Parrot“PlayerController einzurichten. Ausgehend vom BeginPlay-Knoten fügen wir Mapping-Kontext für IMC_Gameplay hinzu.
Der Prioritätsparameter ist hier wichtig. Input-Mapping-Kontexte werden nach ihrer Priorität bewertet, was bei der Überlagerung von Kontexten beachtet werden sollte. Vorerst verwenden wir nur den Gameplay-Kontext.
Beachte, dass der Parameter Notify User Settings hier auf true gesetzt ist – dies ist für das spätere Laufzeit-Input-Remapping notwendig.
Nachdem dein Mapping-Kontext fertig ist, musst du nur noch die erweiterten Input-Event-Knoten zu den Aktionen hinzufügen, die dich interessieren. Hier ist ein Beispiel für eine Sprungaktion:
Die Aktion beginnt, wenn der Spieler die Taste drückt, und ist beendet, wenn der Spieler die Taste loslässt. Sieh dir die übrigen Input-Aktionen in BP_ParrotPlayerController an, um zu sehen, wie andere Input-Typen verarbeitet werden. Du kannst, wenn du das bevorzugst, auch Input-Events in C++ binden, was in der offiziellen Dokumentation beschrieben ist.
Laufzeit-Input-Remapping
Enhanced Input bietet die Möglichkeit, an Input-Aktionen gebundene Tasten zur Laufzeit neu zu belegen. Es sei darauf hingewiesen, dass diese Funktion zwar funktioniert, aber noch experimentell ist, so dass bei der Verwendung für die Produktion Vorsicht geboten ist. In „Parrot“ gibt es einen Bildschirm Tastaturbelegungen, auf dem der Spieler seine Tasten neu belegen kann. Um dies zu erreichen, koppeln wir Enhanced Input mit dem Common UI-Plugin von Epic Games, um die richtigen Metadaten für die Widgets auf dem Bildschirm bereitzustellen. Die allgemeine Einrichtung von Common UI wird in der Dokumentation Benutzeroberfläche behandelt und du solltest diesen Abschnitt lesen, bevor du fortfährst. Wenn dieses Plugin eingerichtet ist, kannst du auch plattformspezifische UI-Elemente anzeigen.
Aktiviere zunächst in den Projekteinstellungen die Benutzereinstellungen für Enhanced Input. Diese findest du unter Bearbeiten > Projekteinstellungen > Engine > Enhanced Input. Nimm deine Einstellungen wie folgt vor:
Navigiere dann zu einem Input Action-Asset und passe die Player Mappable Key Settings an. Das Feld Name muss über alle deine Input-Aktionen einzigartig sein. Anzeigename und Kategorie werden in „Parrot“ lokalisiert.
Du kannst auch die Player Mappable Key Settings außer Kraft setzen, wenn du eine Taste in einem IMC definierst. Für die Sprungaktion im IMC Gameplay haben wir diese Einstellung auf „Einstellungen von Aktion übernehmen“ belassen, so dass wir hier nichts Besonderes tun müssen.
Wenn du deinen Input Mapping Context zum Player-Controller-Blueprint hinzufügst, stelle sicher, dass der Parameter Notify User Settings auf true gesetzt ist.
Der nächste Teil wird sich damit befassen, wie wir Enhanced Input-Aktionen mit Common UI verbinden können. Wir werden behandeln, was für Input Remapping in „Parrot“ erforderlich ist, aber diese Dokumentation ist eine Ergänzung zum offiziellen „Common UI“-Schnellstart-Leitfaden.
Für unseren nächsten Schritt haben wir einen neuen IMC erstellt: IMC_UI_Generic unter Content/Input/UI.
Du solltest das Feld „Player Mappable Key Settings“ für jede Input-Aktion festlegen und auf das entsprechende UI-Metadaten-Asset verweisen. Hier ein Beispiel für die generische Input-Aktion „Annehmen“ und das Metadaten-Asset selbst.
Diese IMC und Input-Aktionen sind notwendig, damit Common UI weiß, welche Aktionen durch die UI-Navigation ausgelöst werden. Die generischen Input-Aktionen „Annehmen“ und „Zurück“ sind die wichtigsten Beispiele dafür, denn ein Spieler wird sie immer aufrufen wollen, wenn er durch die Bildschirme der Benutzeroberfläche navigiert. Wir definieren diese Zuordnungen in einem CommonUI-spezifischen Daten-Blueprint, der eine Subklasse von CommonUIInputData ist.
Setze dann unter Bearbeiten > Projekteinstellungen > Allgemeine Inputeinstellungen die Inputdaten auf deinen generischen Inputdaten-Blueprint.
Nachdem du die wichtigsten Felder festgelegt hast, kannst du mit dem Einrichten deiner Widget-Bildschirme fortfahren. Du beginnst mit einer grundlegenden Parrot-Bildschirm-Klasse für statische Bildschirme und einer aktivierbaren Klasse für andere Bildschirme. Statische Bildschirme sind zum Beispiel das HUD, in dem du dich nicht um die UI-Navigation kümmern musst. Ein aktivierbarer Bildschirm ist zum Beispiel das Pausenmenü, da dieses wissen muss, wann die Schaltfläche „Zurück“ gedrückt wird und es im Spiel-Layout auf der Menüebene sitzt.
Die Bildschirmhierarchie wird in der Dokumentation Benutzeroberfläche behandelt, aber als Referenz wird sie hier wiederholt:
In den Klassenvorgaben von BP-Bildschirmen wird ein optionaler Input-Mapping-Kontext festgelegt. Dies wird bei der Aktivierung/Deaktivierung des Widgets angewendet und kann für jede Klasse überschrieben werden.
UParrotActivatableScreen hat eine Implementierung für die Handhabung von Zurück-Aktionen. Der IA_UI_GenericBack-Event-Listener ist im Event Graph von abgeleiteten Blueprints definiert, die ihn verwenden. Du musst auch das Kontrollkästchen Is Back Handler im Details-Panel aktivieren.
In den Kommentaren in der C++-Klasse und in BP wird erläutert, wie das Zurück-Muster in verschiedenen Bildschirm-Widgets verwendet wird.
Nachdem die Basisklassen definiert sind, schauen wir uns den Bildschirm mit den Tastaturbelegungen an. WBP_KeyBindingsScreen befindet sich unter Content/UI/Widgets/Screens. Es lohnt sich, den Event Graph selbst zu überprüfen, um zu sehen, wie die User Settings und das Key Profile abgefragt werden, um die Typen des Player Key Mapping von Enhanced Input zu erhalten. Die Daten werden zum Hinzufügen und Auffüllen von WBP_InputSelectorBox-Widgets verwendet. Im WBP_InputSelectorBox-Widget findest du zwei W_ParrotInputSelector-Widgets.
Eins wird für Gamepad-Inputs und eins für Tastatur-Inputs verwendet. Der Parrot Input Selector ist ein benutzerdefiniertes Widget, das von dem integrierten Input Selector Widget inspiriert wurde. Beide Widgets gehen in einen Auswahlzustand über, warten auf einen Input und aktualisieren dann die Anzeige:
Bei Maus und Tastatur arbeiten wir mit dem vom Enhanced Input Subsystem zurückgegebenen Text und aktualisieren die Anzeige.
Die Gamepad-Implementierung stützt sich auf Common UI, um Controller-spezifische Bilder abzufragen. In diesem Fall haben wir eine für Xbox-Bilder mit dem Namen
CommonInput_Gamepad_XboxunterContent/Input/UI/Platformeingerichtet. Diese Klasse leitet sich vonUCommonInputBaseControllerDataab.
Abgeleitet von dieser Klasse kannst du Input-Tasten Eingabebilder (Brushes) zuordnen. Richte als Nächstes die Controller-Daten unter Bearbeiten > Projekteinstellungen > Allgemeine Input-Einstellungen ein und navigiere dann zur Plattform.
Wenn diese Daten verbunden sind, findet der Rest der Arbeit in den Widgets statt. Der Code und die Kommentare in UParrotInputSelector und WBP_InputSelectorBox sind einen Blick wert, um genau zu sehen, wie die Remapping-Funktionalität unter Verwendung der Subsysteme Enhanced Input und Common UI funktioniert.
Die letzte wichtige Funktion, die hervorzuheben ist, ist die Speicherung der zugewiesenen Tasten. Dies geschieht in SaveKeyMappings in WBP_KeyBindingsScreen. Diese Funktion durchläuft alle Selector-Box-Widgets und verwendet dann die in den Benutzereinstellungen integrierten Funktionen Apply Settings und Save Settings. Save Settings schreibt eine Datei zum Speichern des Spiels, EnhancedInputUserSettings.sav, auf die Festplatte. Sie befindet sich unter Project Directory > Parrot > Saved-SaveGames.
Wenn alles richtig eingerichtet wurde, solltest du einen funktionierenden Tastenbelegungsbildschirm haben!
In der rechten unteren Ecke befindet sich ein Aktions-Widget, das aktualisiert wird, wenn die Taste neu belegt wird. Dieses Widget heißt WBP_ParrotGamepadActionWidget und befindet sich unter Content/UI/Widgets/Common. Die Klasse UCommonActionWidget von Common UI wird intensiv genutzt, um plattformspezifische Symbole anzuzeigen, wenn eine Input-Aktion unter Verwendung der zuvor erstellten gemeinsamen Input-Daten erfolgt. Durch die Nutzung von Common UI ist es einfach, bei Bedarf neue Widgets zu erstellen, die auf die Enhanced Input-Aktionen deines Spiels verweisen.