Enhanced Input
Enhanced Input to wtyczka własna stworzona przez Epic Games, której używamy w Parrot. Jeśli korzystasz z najnowszej wersji Unreal Engine 5, ta wtyczka powinna być domyślnie włączona. Możesz to sprawdzić, wybierając kolejno Edit (Edycja) > Plugins (Wtyczki) i zaznaczając odpowiednie pole wyboru.
Enhanced Input zastępuje domyślny system sterowania w silniku Unreal Engine i stanowi standard w zakresie obsługi złożonych danych wejściowych lub zmiany przypisania sterowania w czasie wykonywania programu. Oficjalna dokumentacja Epic Games zawiera doskonałe omówienie tego systemu wraz z instrukcją konfiguracji zasobów danych wejściowych.
Podstawowe koncepcje
Powtarzając oficjalną dokumentację, oto lista podstawowych koncepcji związanych z Enhanced Input, z którymi należy się zapoznać:
Input Actions (Działania gracza)
Input Mapping Contexts (IMCs) (Konteksty przypisania działań gracza)
Input Modifiers (Modyfikatory działań gracza)
Input Triggers (Wyzwalacze działań gracza)
Jeśli masz doświadczenie w korzystaniu z nowego systemu sterowania Unity, te pojęcia powinny być ci znane.
Input Actions (Działania gracza) najlepiej można opisać jako „działania wykonywane w grze” w określonym kontekście gry. Na przykład, jeśli postać znajduje się w samochodzie, potrzebne będą działania takie jak „przyspieszenie” lub „hamowanie”.
Input Mapping Contexts (Konteksty przypisania działań gracza) również pasują do tego przykładu. Jeśli gracz wsiada do samochodu lub z niego wysiada, możesz chcieć zmienić działanie niektórych klawiszy lub przycisków pada.
Input Triggers (Wyzwalacze działań gracza) zapobiegają uruchomieniu działania, dopóki nie zostaną spełnione wszystkie warunki wyzwalacza. Na przykład możesz chcieć, aby gracz przytrzymał przycisk przez określony czas, aby wyzwolić działanie.
Input Modifiers (Modyfikatory działań gracza) zmieniają wartość samego działania. Strefy neutralne (Dead Zones) są popularnymi modyfikatorami działań gracza używanymi do łatwiejszego przetwarzania pierwotnych danych wejściowych. Enhanced Input rozwiązuje wszystkie te problemy po odpowiedniej konfiguracji.
Spójrzmy na przykład w grze Parrot. W Content/Input/Gameplay znajdziesz folder Actions (Działania) oraz plik zasobu IMC_Gameplay. W folderze Actions (Działania) znajdź zasób IA_Jump.
Typ wartości to Digital (bool), co oznacza typ wyjścia tego działania. W sekcji wyzwalaczy dostępne są następujące typy:
Naciśnięto
Zwolniono
Patrząc na to działanie gracza, można stwierdzić, że niezależnie od tego, jaki klawisz lub przycisk jest przypisany, musi on zostać wyzwolony poprzez naciśnięcie i mieć stan wyjściowy typu logicznego (bool). Zwolnienie przycisku wyzwala zakończenie działania. Kolejną ważną informacją jest to, że zarówno wyzwalacze, jak i modyfikatory mogą zostać nadpisane przez kontekst przypisania działań gracza. Przyjrzyjmy się kontekstowi przypisania działań gracza w rozgrywce, aby zobaczyć, jak w praktyce działa nadpisywanie modyfikatorów.
IA_MoveAxis nie ma ustawionego wyzwalacza, więc wartość osi X lewej gałki gamepada (Gamepad Left Thumbstick X-Axis) zostanie odczytana natychmiast po wykryciu zmiany. Aby ułatwić przetwarzanie pierwotnych danych wejściowych, używamy modyfikatora neutralnej strefy (Dead Zone), aby ustawić górną i dolną granicę danych wejściowych.
Przykładem, w którym nie zapewniamy nadpisania w IMC, jest przypisanie skoku.
Tutaj można zauważyć, że wyzwalacz pochodzi z samego działania gracza, więc nie ma potrzeby definiowania wyzwalacza w przypisaniu. Ustawienia są również dziedziczone z działania, ale na razie można to zignorować, ponieważ zostanie to omówione w sekcji dotyczącej ponownego przypisania.
Procesy nasłuchujące zdarzeń w Enhanced Input
Teraz, gdy masz już skonfigurowane zasoby, musisz wprowadzić kilka ustawień dotyczących użycia w czasie wykonywania programu. W Parrot dokonujemy powiązania z podsystemem lokalnego gracza Enhanced Input (Enhanced Input Local Player Subsystem), aby skonfigurować nasze procesy nasłuchujące zdarzeń w BP_ParrotPlayerController. Z węzła BeginPlay dodajemy kontekst mapowania dla IMC_Gameplay.
Ważny jest tutaj parametr priorytetu. Konteksty mapowania działań są przetwarzane według ich priorytetu, więc należy o tym pamiętać podczas nakładania warstw kontekstów. Na razie będziesz używać tylko kontekstu rozgrywki.
Należy zwrócić uwagę na parametr Notify User Settings (Powiadom ustawienia użytkownika) ustawiony tutaj na true – jest to konieczne do późniejszego ponownego mapowania danych wejściowych w czasie wykonywania programu.
Po przygotowaniu kontekstu mapowania pozostaje tylko dodać węzły zdarzeń Enhanced Input do interesujących cię działań. Oto przykład dla skoku:
Działanie rozpoczyna się, gdy gracz naciśnie przycisk, a kończy się, gdy gracz zwolni przycisk. Spójrz na pozostałe działania gracza w BP_ParrotPlayerController, aby zobaczyć, jak przetwarzane są inne typy danych wejściowych. Jeśli wolisz, możesz również powiązać zdarzenia wejścia w C++, co opisano w oficjalnej dokumentacji.
Ponowne mapowanie danych wejściowych
Enhanced Input ma możliwość ponownego mapowania klawiszy powiązanych z działaniami gracza w czasie wykonywania programu. Warto pamiętać, że chociaż ta funkcja działa, to wciąż jest w fazie eksperymentalnej, więc zachowaj ostrożność, używając jej w gotowym projekcie. W Parrot mamy ekran Key Bindings (Przypisanie klawiszy), który pozwala graczowi zmienić przypisanie klawiszy. Aby to zrobić, łączymy Enhanced Input z wtyczką Epic Games Common UI, żeby dostarczyć odpowiednie metadane do widżetów ekranu. Konfiguracja Common UI jest opisana w dokumentacji Interfejs użytkownika i warto ją przeczytać przed przejściem dalej. Po skonfigurowaniu tej wtyczki możesz też wyświetlać elementy interfejsu specyficzne dla danej platformy.
Aby rozpocząć, włącz ustawienia użytkownika dla Enhanced Input w ustawieniach projektu. Znajdują się one w Edit (Edycja) > Project Settings (Ustawienia projektu) > Engine (Silnik) > Enhanced Input. Skonfiguruj ustawienia w następujący sposób
Następnie przejdź do zasobu działania gracza i dostosuj Player Mappable Key Settings (Ustawienia mapowalnych klawiszy gracza). Pole Name (Nazwa) musi być unikalne dla wszystkich działań gracza. Pola Display Name (Nazwa wyświetlana) i Category (Kategoria) są w Parrot dostosowane do lokalizacji.
Ustawienia mapowalnych klawiszy gracza można również nadpisać podczas definiowania klawisza w IMC. W przypadku działania skoku w Gameplay IMC pozostawiliśmy to ustawienie jako „Dziedzicz ustawienia z działania” (Inherit Settings from Action), więc nie musimy wykonywać żadnych dodatkowych czynności.
Sprawdź, czy podczas dodawania kontekstu mapowania danych wejściowych w blueprincie kontrolera gracza parametr Notify User Settings (Powiadom ustawienia użytkownika) jest ustawiony na true.
W następnej części omówimy, jak połączyć działania Enhanced Input z Common UI. Omówimy wymagania dotyczące zmiany mapowania wprowadzania danych wejściowych w Parrot, ale niniejsza dokumentacja stanowi uzupełnienie oficjalnego poradnika Common UI Quickstart Guide (Skrócony poradnik Common UI).
W następnym kroku utworzyliśmy nowy IMC: IMC_UI_Generic w Content/Input/UI.
Należy ustawić pole Player Mappable Key Settings (Ustawienia mapowalnych klawiszy gracza) dla każdego działania gracza i wskazać odpowiedni zasób danych metadanych interfejsu użytkownika. Oto przykład ogólnego działania gracza Accept (Akceptuj) i samego zasobu metadanych.
Te IMC i działania gracza są niezbędne, aby Common UI rozpoznawał działania wywołane przez nawigację interfejsu użytkownika. Ogólne działania gracza Accept (Akceptuj) i Back (Wstecz) są tego podstawowymi przykładami, ponieważ gracz zawsze będzie chciał je wywołać podczas nawigacji po ekranach interfejsu użytkownika. Mapowania te definiujemy w blueprincie danych specyficznym dla CommonUI, który jest podklasą CommonUIInputData.
Następnie w obszarze Edit (Edycja) > ProjectSettings (Ustawienia projektu) > Common Input Settings (Wspólne ustawienia wejściowe) ustaw dane wejściowe na swój ogólny blueprint danych wejściowych.
Gdy ważne pola są już ustawione, można przejść do konfiguracji ekranów widżetów. Zacznij od podstawowej klasy Parrot – klasy ekranu dla ekranów statycznych i klasy z możliwością aktywacji dla pozostałych ekranów. Ekrany statyczne to na przykład HUD, gdzie nie trzeba martwić się o nawigację w interfejsie użytkownika. Przykładem ekranu z możliwością aktywacji jest menu wstrzymania gry, ponieważ musi ono wiedzieć, kiedy zostanie naciśnięty przycisk Wstecz; znajduje się w warstwie Menu w układzie gry.
Hierarchia ekranów została omówiona w dokumentacji Interfejs użytkownika, ale dla przypomnienia została powtórzona poniżej:
W domyślnych ustawieniach klas dla BP ekranów ustawiliśmy opcjonalny kontekst mapowania danych wejściowych. Jest on stosowany podczas aktywacji/dezaktywacji widżetu i można go nadpisać dla poszczególnych klas.
UParrotActivatableScreen ma implementację do obsługi działania Wstecz. Proces nasłuchujący zdarzeń IA_UI_GenericBack jest zdefiniowany w grafie zdarzeń pochodnych blueprintów, które z niego korzystają. Należy również zaznaczyć pole wyboru Is Back Handler w panelu Details (Szczegóły).
Zapoznaj się z komentarzami w klasie C++ i BP, aby zobaczyć, jak wzorzec Back (Wstecz) jest używany w różnych widżetach ekranowych.
Po zapoznaniu się z klasami bazowymi, spójrz na ekran powiązań klawiszy. WBP_KeyBindingsScreen znajduje się w folderze Content/UI/Widgets/Screens. Warto samodzielnie przeanalizować graf zdarzeń, aby zobaczyć, w jaki sposób zapytania User Settings (Ustawienia użytkownika) i Key Profile (Profil klawisza) są odpytywane w celu pobrania typów Player Key Mapping (Mapowanie klawiszy gracza) z Enhanced Input. Dane te są wykorzystywane do dodawania i wypełniania widżetów WBP_InputSelectorBox. Wewnątrz widżetu WBP_InputSelectorBox znajdują się dwa widżety W_ParrotInputSelector.
Jeden służy do wprowadzania danych z gamepada, a drugi do wprowadzania danych z klawiatury. Parrot Input Selector to niestandardowy widżet inspirowany wbudowanym widżetem Input Selector. Oba te widżety przechodzą w stan wyboru, czekają na wprowadzenie danych, a następnie aktualizują wyświetlacz:
W przypadku myszy i klawiatury pracujemy z tekstem zwróconym z podsystemu Enhanced Input i aktualizujemy wyświetlacz.
Implementacja gamepada opiera się na Common UI w celu zapytania o grafiki specyficzne dla kontrolera. W tym przypadku skonfigurowaliśmy jeden dla grafik Xbox o nazwie
CommonInput_Gamepad_XboxwContent/Input/UI/Platform. Ta klasa jest pochodną klasyUCommonInputBaseControllerData.
Tworząc klasę pochodną na podstawie tej klasy, można mapować klawisze wejściowe do obiektów z grafikami. Skonfiguruj dane kontrolera w Edit (Edycja) > Project Settings (Ustawienia projektu) > Common Input Settings (Wspólne ustawienia wejściowe), a następnie przejdź do platformy.
Po podłączeniu tych danych pozostała część pracy odbywa się w widżetach. Warto zapoznać się z kodem i komentarzami w UParrotInputSelector i WBP_InputSelectorBox, aby dokładnie zrozumieć, jak działa funkcja zmiany mapowania przy użyciu podsystemów Enhanced Input i Common UI.
Ostatnią ważną funkcjonalnością, na którą należy zwrócić uwagę, jest sposób zapisywania mapowanych klawiszy. Odbywa się to w SaveKeyMappings w WBP_KeyBindingsScreen. Funkcja ta iteruje po wszystkich widżetach pól selektora, a następnie korzysta z wbudowanych funkcji ustawień użytkownika Apply Settings (Zastosuj ustawienia) i Save Settings (Zapisz ustawienia). Save Settings (Zapisz ustawienia) zapisuje plik zapisu gry EnhancedInputUserSettings.sav na dysku. Znajduje się on w Project Directory (Katalog projektu) > Parrot > Saved-SaveGames.
Jeśli wszystko zostało skonfigurowane poprawnie, ekran przypisania klawiszy powinien działać!
Możesz zauważyć, że w prawym dolnym rogu znajduje się widżet działania, który aktualizuje się po zmianie mapowania klawisza. Widżet ten nosi nazwę WBP_ParrotGamepadActionWidget i znajduje się w folderze Content/UI/Widgets/Common. Wykorzystuje on w znacznym stopniu klasę UCommonActionWidget Common UI, która została stworzona w celu wyświetlania ikon specyficznych dla platformy na podstawie działania gracza przy użyciu wspólnych danych wejściowych, które utworzyliśmy wcześniej. Korzystając z Common UI, można w prosty sposób tworzyć nowe widżety, które odwołują się do działań Enhanced Input w grze.