UMG
System interfejsu użytkownika Unreal nosi nazwę Unreal Motion Graphics lub UMG. Różni się on znacznie od standardowego systemu uGUI stosowanego w Unity. Jeśli znasz już system Unity, to narzędzie do tworzenia interfejsu użytkownika UI Designer stosowane w UMG najbardziej przypomina narzędzie UI Toolkit UI Builder. Narzędzie UI Designer zostało szczegółowo opisane w oficjalnej dokumentacji; strony Building Your UI (Budowanie interfejsu użytkownika) i UMG Best Practices (Najlepsze praktyki w zakresie UMG) będą szczególnie przydatne dla deweloperów przechodzących z Unity. Sercem UMG są widżety, czyli seria gotowych funkcji i hierarchii, które można wykorzystać do budowy interfejsu użytkownika.
CommonUI
CommonUI to wtyczka własna stworzona przez Epic Games, której używamy w Parrot. CommonUI ustawia „wspólne” style i działania dla wszystkich widżetów, co normalnie zajęłoby dużo czasu, gdyby trzeba było to robić ręcznie za każdym razem. Praktycznym przykładem jest wykrywanie zmian urządzeń wejściowych i automatyczne przełączanie ikon wejściowych na ekranie. Ręczne wykonanie tej czynności zajęłoby dużo czasu, ale Common UI automatyzuje ten proces. CommonUI jest również wymagane do obsługi funkcji zmiany przypisania klawiszy w Enhanced Input, co zostało szczegółowo opisane w dokumentacji Enhanced Input.
Aby skonfigurować CommonUI, należy najpierw włączyć tę opcję w oknie Plugins (Wtyczki). W menu wybierz kolejno opcje Edit (Edycja) > Plugins (Wtyczki), wyszukaj „Common UI Plugin” (Wtyczka Common UI), włącz ją, a następnie uruchom ponownie edytor.
Przejdź do Project Settings (Ustawienia projektu) > General Settings (Ustawienia ogólne) i zmień Game Viewport Client Class (Klasa klienta okna wizualizacji gry) z „GameViewportClient” na „CommonGameViewportClient”. Dzięki temu widżety CommonUI mogą odbierać zdarzenia wejściowe z silnika.
Pod opcją Project Settings (Ustawienia projektu) > Common Input Settings (Wspólne ustawienia wejściowe) zaznacz pole wyboru Enable Enhanced Input Support (Włącz obsługę Enhanced Input). Dzięki temu Enhanced Input będzie działać z CommonInput. CommonInput odpowiada za wprowadzanie danych w widżetach CommonUI.
Na koniec musisz włączyć niektóre moduły w projekcie, aby móc korzystać z nich w kodzie. Przejdź do pliku
$ProjectName.Build.cs, w tym przypadku jest to plikParrot.Build.cs. Dodaj następujące moduły do listy PublicDependencyModuleNames:CommonInputCommonUIEnhancedInputGameplayTagsUMG
Hierarchia widżetów specyficznych dla Parrot
Pierwsza klasa interfejsu użytkownika, którą należy przeanalizować w Parrot, to AParrotHUD. Klasa HUD w Unreal Engine jest aktorem utworzonym dla każdego lokalnego gracza i obsługuje wyświetlanie informacji na ekranie. Ma kanwę i kanwę do debugowania, na której można bezpośrednio rysować. Można ją również przypisać jako część konfiguracji trybu gry. W Parrot klasa ta jest używana jako aktor posiadający widżet główny, z którego tworzone są i zarządzane wszystkie widżety.
Typ klasy dla tego widżetu będącego właścicielem jest UParrotGameLayout. UParrotGameLayout jest podstawowym kontenerem widżetów C++ dla wszystkich innych widżetów UI. Wewnątrz znajduje się lista „warstw” typu UCommonActivatableWidgetContainerBase. Wszystkie inne widżety, które chcesz wyświetlić, zostaną umieszczone w jednej z tych warstw.
Podstawowe warstwy, które utworzyliśmy, to:
Game (Gra): warstwa, w której umieszczasz widżet HUD UMG
GameMenu: warstwa, w której umieszczasz dowolny widżet, który chcesz wyświetlić nad HUD.
Menu: warstwa dla wszystkich widżetów ekranu, takich jak ekran pauzy, ekran ustawień, ekran ekwipunku i inne podobne ekrany.
Modal: warstwa dla wszystkich modalnych wyskakujących okienek.
Jednocześnie aktywny może być tylko jeden widżet dla każdej warstwy. Możesz umieścić kilka różnych widżetów ekranu w warstwie „Menu”, ale aktywny i widoczny będzie tylko ostatni z nich.
W Parrot stworzyliśmy również hierarchię klas dla ekranów, które można aktywować, ponieważ wszystkie te widżety mają wspólną funkcjonalność i są umieszczane w warstwie Menu. Hierarchia klas wygląda następująco:
Wszystkie ekrany interfejsu użytkownika w Parrot są tworzone przy użyciu tej konfiguracji.
Stylizacja widżetu
Dzięki wtyczce Common UI i konfiguracji ekranu możesz rozpocząć stylizację swoich widżetów. Dobrym przykładem jest W_ButtonBase znajdujący się w Content/UI/Widgets/Common. Wykorzystuje on dane stylizacji ButtonStyle_Base znajdujące się w folderze Content/UI/Styling. Wykorzystuje klasę UCommonButtonStyle z Common UI. Dostępnych jest wiele opcji, które można dostosować. Przykładami są dźwięki i pędzle oparte na stanie przycisku. Common UI posiada wiele różnych klas stylizacji, takich jak ta, w zależności od używanego widżetu. Jeśli chcesz wykonać własną stylizację, dobrym punktem odniesienia jest kod silnika tych stylizowanych widżetów.
Ekran wczytywania
Ekran wczytywania w grze Parrot wykorzystuje wtyczkę własną autorstwa Epic Games: CommonLoadingScreen. Inny przykład zastosowania tej wtyczki można znaleźć w przykładowym projekcie Lyra od Epic Games. Aby zrozumieć, dlaczego używamy tej wtyczki, musimy najpierw zapoznać się z podstawami ładowania poziomu w Unreal Engine.
W UE istnieje kilka sposobów obsługi ładowania poziomów. Prostym rozwiązaniem jest wywołanie w blueprincie węzła Open Level (Otwórz poziom). Ta funkcja może wczytać mapę na podstawie ciągu tekstowego lub miękkiego odwołania do obiektu mapy. Działa to dobrze w przypadku prostych map, ale jest pewien haczyk. Po wywołaniu tej funkcji mapa jest ładowana synchronicznie, co może powodować zauważalne zacięcia w zależności od ilości danych, które muszą zostać załadowane dla nowej mapy. Kolejnym problemem jest to, że widżet dodany do okna wizualizacji zostanie powiązany z kontrolerem gracza istniejącym w poprzednim poziomie. Kiedy następuje przejście do kolejnego poziomu, zostanie on wyczyszczony w ramach wyładowania poziomu.
Korzystne może być załadowanie nowego trybu gry w oparciu o mapę (na przykład poziom dla jednego gracza w przeciwieństwie do poziomu dla wielu graczy). Ale jak zachować ekran wczytywania i uniknąć potencjalnych problemów z ładowaniem przy użyciu funkcji Open Level (Otwórz poziom)? Przyjrzyjmy się BP_ParrotGameInstance
Asynchroniczne ładowanie poziomu rozwiązuje problem braku gotowości zasobów w momencie wywołania funkcji Open Level (Otwórz poziom). Jak wspomniano w komentarzu, obsługa ekranu wczytywania również została już tutaj zaimplementowana. Konfiguracja wtyczki jest prosta i można ustawić widżet ekranu wczytywania w menu Edit (Edycja) > Project Settings (Ustawienia projektu) > Common Loading Screen (Wspólny ekran wczytywania).
Zwróć też uwagę na przełączanie debugowania. Testowanie za pomocą tych opcji w edytorze pozwala lepiej ocenić, jak ekran wczytywania będzie działał w spakowanej wersji.
Teraz poziomy ładują się wraz z ekranem wczytywania. Warto samodzielnie zapoznać się z BP_ParrotGameInstance, aby zobaczyć, jak skonfigurowaliśmy kolejność poziomów dla trybu jednoosobowego i wieloosobowego. Konfiguracja stanu gry została omówiona w dokumentacji Struktura rozgrywki Unreal.