Wirtualna Rzeczywistość w Unreal Engine 5?

Witajcie. Dziś, chciałbym porozmawiać z Wami o wirtualnej rzeczywistości. Chciałbym pokazać Wam jak rozpocząć przygodę z developmentem pod VR (PC/console), a przy okazji – jak zafundować sobie kawał świetnej zabawy z Unreal Engine 5 oraz Meta Quest 2. Nie ukrywam – będą to szybkie rozważania w formie poradnika, które oprzemy o fantastyczną wbudowaną templatkę VR – zatem zakładam, że podstawy Unreal Engine są Wam znane. Oczekuję również, że wiecie jak podstawowo posługiwać się goglami VR. Skupimy się akurat na Meta Quest 2, ale poruszymy uniwersalne rozwiązania – zatem posiadacze innego sprzętu również skorzystają. Pogadamy o podstawowym setupie, budowaniu scen, interakcjach, wygodzie użytkownika i innych. Najpierw jednak…

VR w UE5. Czy to w ogóle możliwe?

Pytam raczej retorycznie, ale warto wspomnieć o kilku aspektach. Unreal Engine wspiera VR już od dość długiego czasu. Również piąta wersja silnika pozwala na budowanie aplikacji VR (tych mobilnych jak i PC/console VR). Istnieją jednak pewne ograniczenia (zwłaszcza graficzne). Wszyscy dobrze wiemy, że najnowszy Unreal Nanitem i Lumenem stoi. Niestety nie do końca jeżeli chodzi o PC VR, a w ogóle jeżeli mówimy o mobile VR (jakim jest Quest 2). Dla małych scen, odpowiednio dobrane ustawienia pozwolą nam użyć Lumena (choć nie do końca stabilnie i bez stuprocentowej pewności, że coś się przypadkiem nie “wykrzaczy”), ale tylko na mocnym sprzęcie. O Ray Tracingu i DLSS również możemy zapomnieć. No i dodatkowo pojawiają się błędy w niektórych ustawieniach post processingu oraz zostają narzucone nam konkretne ustawienia projektu. Brzmi nie do końca zachęcająco? To nic! Serio. Dlaczego? Ano: aby uzyskać fotorealistyczne efekty pozostają nam stare dobre sztuczki jak Lightmapping, Reflection Probes czy inne wygibasy, o części których na pewno wspomnimy za chwilę. Trochę dodatkowej pracy, trochę pomysłu, a na pewno znajdą się tak zwane “workarounds”. Nie przedłużając, odpowiadając na pytanie: Tak, VR w UE5 jest możliwy. Bierzemy się do pracy. Do dzieła!

Czego potrzebujemy?

Nasz projekt oprzemy o wersję 5.1.1 silnika Unreal. Jest to na ten moment najnowsza, najbardziej aktualna wersja. Potrzebujemy również gogli wirtualnej rzeczywistości. Jak już wspomniałem wcześniej, będzie to Meta Quest 2.

W tym miejscu pragnę się na moment zatrzymać. Rozpoczynając development na jakąkolwiek platformę, ważne jest, aby tę platformę posiadać (przede wszystkim do testów w trakcie produkcji). Niby banał, a jednak. Nie wyobrażam sobie sytuacji, w której buduję aplikację na przykład na smartfon Android bez telefonu do testów lub buduję na PlayStation bez konsoli pod ręką. Owszem, są emulatory, ale żaden emulator nie zastąpi docelowej platformy. Ot taka dygresja. Wracając, oprócz samych gogli potrzebujemy również Quest Link – kabelek którym podłączymy gogle do komputera – oraz oprogramowanie Quest, aby móc uruchamiać aplikacje Rift VR (środowisko OpenXR dla PC VR, również dla Unreal Engine). Trochę pogmatwane? Dla niewtajemniczonych tłumaczę. Nabywając Meta Quest 2 dostajemy gogle mobilne i samowystarczalne (jest to wariacja systemu Android) bez możliwości połączenia ich z komputerem. Aby połączyć je z komputerem i uruchamiać wysokiej jakości aplikacje VR (w tym, sam Unreal Engine) musimy zakupić specjalnie do tego przeznaczony kabelek. Po podłączeniu Quest 2 do komputera i zainstalowaniu oprogramowania zamienia się on w Rift. Warto wspomnieć, że przyda się update sterowników, Windowsa i w ogóle update wszystkiego połączonego – Questa 2, oprogramowania Quest.

Kiedy cały sprzęt zostanie przygotowany, sterowniki i oprogramowanie zupdatowane a Unreal 5.1.1 pobrany – przejdziemy dalej.

Templatka VR

Na samym początku rzuciłem, że przy tworzeniu projektu skorzystamy z gotowego szablonu. Och, uwierzcie mi, cóż to za templatka! Jest to stosunkowo świeża rzecz – choć co prawda Unreal posiadał już wcześniej szablon VR, ale nie tak rozbudowany jak ten aktualny. Template ten został przygotowany na bazie standardu OpenXR i w praktyce gotowy jest do użycia z PC, konsolami i mobilkami oraz szeroką gamą gogli (i okularów – w standardzie OpenXR buduje się aplikacje VR, AR oraz MixedReality). Szablon napisany w całości w Blueprintach zawiera takie ficzery jak: podstawowy input,  spacer na zasadzie teleportacji, skokowe obracanie się, podnoszenie przedmiotów, broń, widgety czy tak zwaną Spectator Camera (dla obserwatora). Posiada również przygotowany testowy level (bez Lumenów, ale oświetlony wybejkowanym światłem), na którym można zapoznać się z funkcjonalnościami lub, który można rozbudować.

Przyjrzyjmy się teraz kilku ficzerom. Po uruchomieniu Unreal Engine 5.1.1 zakładamy nowy projekt na bazie Virtual Reality Template. Zwróćcie uwagę, że konfiguracja polega wyłącznie na zdecydowaniu się na Starter Content. Nie mamy tutaj opcji jak przy innych templatkach – RayTracing, C++ albo Blueprinty (choć nic nie stoi na przeszkodzie aby rozbudowywać w C++), itp. Utworzony projekt został dla nas skonfigurowany – zostały dobrane odpowiednie zmienne, ustawienia projektu oraz pluginy.

Po uruchomieniu projektu widzimy następujący level. Jest to nieduża scena z 48 aktorami gotowa do gry w goglach. No właśnie. Jak odpalić podgląd tego projektu w VR? Niestety standardowy Play tutaj nie zadziała. Jeżeli podpięliśmy Questa 2 do komputera, uruchomiliśmy oprogramowanie Quest i nasze gogle są rozpoznawalne, wtedy otwieramy projekt – a naszym oczom ukazuje się nowa opcja: VR Preview, zaraz obok standardowego Play. Po kliknięciu gra startuje w goglach z podglądowym oknem na monitorze (co ciekawe – istnieje możliwość, aby w goglach odpalić również inne templatki). I teraz uwaga. Niestety VR Preview lubi się crashować/freezować. Nie jest to częste, ale się zdarza. Jak sobie z tym radzić? Zazwyczaj pomaga klasyczne “wyłącz i włącz”. Najczęściej wystarczy zrestartować projekt Unreala, rzadziej trzeba również zrestartować oprogramowanie Quest i ponowić połączenie z komputerem, a już bardzo rzadko trzeba zrestartować komputer i gogle (no niestety ten restart jest najbardziej nieprzyjemny, ale co zrobić – takie życie developera). Dobra, wracamy. Podstawową interakcją jest poruszanie się. Szablon stawia na mało inwazyjny i przyjemny system teleportacji. Co mam na myśli? Chorobę symulacyjną. Płynne poruszanie się u wielu osób wywołuje nieprzyjemny stan, a jak wiadomo wygoda użytkownika jest bardzo ważna – zatem teleport sprawdza się idealnie. Teleportacja działa w oparciu o navmesh – to on wyznacza gdzie postać “ma prawo” się teleportować: Następnie: Chwytanie obiektów zostało wykonane na bazie Blueprintowego komponentu, który możemy podpiąć pod dowolny dynamiczny obiekt i zdecydować w jaki sposób chcemy móc łapać przedmiot: swobodnie czy w konkretnym miejscu (na przykład broń). Dodatkowo, w systemie tym dostajemy Eventy, mówiące nam o rozpoczęciu chwytu czy jego zakończeniu: Powiedzmy sobie jeszcze o User Interface. W szablonie zostało przygotowane proste menu wyświetlane przy “ręce”, które umożliwia nam zresetowanie pozycji, restart aplikacji (levelu) czy zamknięcie gry. W templatce jest tego zdecydowanie więcej – przede wszystkim VRPawn i Enhanced Input – ale przejdźmy sobie już do jakiejś konkretnej implementacji. Gdyby ktoś jednak chciał zgłębić i poznać szablon bardziej to odsyłam do dokumentacji.

Budowanie sceny

Pogadaliśmy co nieco o tym jak VR ma się w Unreal Engine, co jest potrzebne aby rozpocząć development, jak ustawić sobie środowisko i co oferuje szablon wirtualnej rzeczywistości. Spróbujmy zatem coś stworzyć. Chodzi mi po głowie rozbudowanie, przykładowego templatkowego levelu. Zrobimy dwa zamknięte pomieszczenia. Pierwsze drzwi otworzą się gdy gracz do nich podejdzie, drugie zaś wymagać będą klucza – jakiegoś przedmiotu, który je aktywuje.

Zacznijmy od edycji sceny. Na początek opróżnimy wnętrze – usuwamy ognisko, dźwięk, dekoracje, światła i volume modyfikacji nawigacji razem z tekstem. Zauważcie, że po usunięciu świateł nadal pozostało cieniowanie. To właśnie wspomniana jedna ze sztuczek na to aby osiągnąć wysokiej jakości (GI) i w miarę tanie oświetlenie w VR – Lightmapping, czyli wypiekanie światła w teksturach (nie tylko w Unrealu). O tej technice moglibyśmy zrobić porządny wykład, ale na ten moment odsyłam do dokumentacji: https://docs.unrealengine.com/5.0/en-US/understanding-lightmapping-in-unreal-engine/ Przebudujmy zatem oświetlenie, aby pozostałości po punktowych światłach zniknęły. W tym celu wybieramy Build > Build All Levels, następnie czekamy aż proces lightmappingu zakończy się. Po zbudowaniu zapisujemy level i jego plik BuildData, w którym siedzą wypieczone lightmapy (przy dużych levelach lub dużej gęstości tekstur lub podkręconych ustawieniach lightmappera rozmiary BuildData jak i czas wypiekania rosną). Uwaga! Czasem, aby zobaczyć wynik przebudowanego światła należy ponownie wczytać level – Unreal tak ma. Podzielmy teraz pomieszczenie na pół – tymi samymi elementami, którymi zostało wykonane wejście i rozstawmy kilka domyślnych punktowych świateł. Po ponownym wybejkowaniu oświetlenia powinniśmy otrzymać. Teraz drzwi, a przy drugich miejsce na “klucz”. W moim przypadku będzie to duch sfery – co oznacza, że jeżeli gracz upuści w tym miejscu małą sferę to drzwi się aktywują. Tym elementom ustawiamy mobilność na Movable, gdyż będziemy nimi manipulować. Dodatkowo – obiekty movable domyślnie nie potrzebują, aby je wypalać w oświetleniu. Setup sceny gotowy, pora na…

Interakcje

Zaczniemy od drzwi, przygotowując na początek animacje otwierania (w moim przypadku rozsuwania). Będą to dwie proste animacje Level Sequence z transformacją pozycji w jednej osi, tak aby drzwi schować w ścianie. Ważne, aby dla ścieżek transformacji zaznaczyć opcję When Finished > Keep State, co pozwoli pozostawić drzwi otwarte po zakończeniu sekwencji.

Pierwsze drzwi mają otworzyć się gdy gracz się do nich zbliży. Użyjemy do tego klasycznego Trigger Volume. Najprościej – trigger ustawiamy przed drzwiami i piszemy skrypt w Level Blueprint. Po wejściu tylko i wyłącznie naszego VRPawn (czyli nas) do triggera raz odpalamy sekwencje dla pierwszych drzwi (sekwencja znajduje się jako aktor na levelu). Uwaga! Aby skrypt zadziałał musimy lekko edytować VRPawn, gdyż ten domyślnie nie ma kolizji oraz (tak jakby) blokuje wejście do triggerów. Z kolizją jest prosta sprawa – po prostu dodajemy komponent sphere collision. Z triggerami wygląda to tak – zrobiłem mały hack (nie do końca optymalny, ale to nic – na początek wystarczy): w funkcji Teleport Trace przed odpaleniem Predict Projectile Path By Object Type pobrałem wszystkich aktorów typu Trigger Volume i podałem ich jako ignorowanych do funkcji Predict Projectile Path By Object Type. Dodatkowo w tej samej funkcji (VRPawn > Teleport Trace) do Predict Projectile Path By Object Type podaję nie tylko obiekty WorldStatic, ale również WorldDynamic po to, aby nie można było teleportować się przez drzwi.

Pierwsze drzwi gotowe! Szybki test w VR i lecimy dalej

Do drugich, jako klucz wykorzystamy tę wielką kulę na levelu – ma ona podpięty komponent Grab, co załatwia sprawę podnoszenia jej. Kulę zmniejszamy do rozmiarów ducha przy drzwiach (dodatkowo ja położyłem kulę na stole, obok broni), a dla naszego ducha ustawiamy opcje: Collision Presets > OverlapAll oraz Generate Overlap Events > True. Następnie znów piszemy skrypt w level blueprint (choć można by pokusić się już o jakiś bardziej rozbudowany system). Co tu się dzieje? Tłumaczę: Na starcie gry tworzę sobie referencję do komponentu Grab z kuli/klucza i przypinam się do eventu OnDropped. Za każdym razem kiedy kula zostanie puszczona przez gracza sprawdzam czy overlappuje już z duchem. Jeżeli overlappuje to: teleportuje kulę dokładnie w miejsce ducha i wyłączam jej fizykę aby została na miejscu, następnie wyłączam możliwość ponownego podniesienia kuli i odpalam animację otwierania drugich drzwi.

Bomba! Właśnie utworzyliśmy drugie drzwi, aktywowane “kluczem”! Nie pozostaje nam nic innego jak przetestować to w VR. Gratulacje, pierwsze koty za płoty – pierwsze VRowe interakcje ogarnięte!

Co dalej?

To był szybki wstęp do VR w Unreal. Dalej już tylko świetna zabawa! Nowe interakcje, optymalizacja istniejących, może jakieś widgety i UI czy praca nad grafiką. Może jakiś gameplay – na przykład ukrycie tego klucza między innymi obiektami, tak aby gracz musiał najpierw się do niego dogrzebać. Potem build aplikacji i dalsze poszerzanie horyzontów przy developmencie pod VR w Unreal Engine 5! Zachęcam!