Eksport na web a port na web: na czym polega różnica
Wersję przeglądarkową można zbudować w Unity, w Godocie i w Construct. Unity ma target Web, Godot szablon eksportu webowego, a gry z Construct od początku działają w HTML5. Na game jam albo do prototypu to zwykle wystarcza.
Kłopoty zaczynają się, gdy gra trafia do prawdziwych graczy. Z tymi problemami klienci przychodzą do nas najczęściej:
- Długie pierwsze ładowanie. Gracz czeka na runtime silnika i większość danych gry, zanim zobaczy menu. Poki zaleca początkowe pobranie do 5 MB i najwyżej 8 MB łącznie. CrazyGames wymaga najwyżej 20 MB, żeby gra mogła pojawić się na mobilnej stronie głównej.
- Przycięcia na telefonach. Build, który na laptopie trzyma stałą liczbę klatek, w Chrome na Androidzie ze średniej półki potrafi gubić klatki.
- Braki pamięci na iOS. Karta przeglądarki dostaje dużo mniej pamięci niż natywna aplikacja. Gdy gra przekroczy limit, Safari przeładowuje stronę.
- Cisza po starcie. Przeglądarki blokują dźwięk do pierwszego kliknięcia albo dotknięcia. Muzyki, która w edytorze gra od razu, w przeglądarce po prostu nie słychać.
- Brak funkcji portalu. Reklamy, rewarded video, zapisy w chmurze i zdarzenia rozgrywki wymagają SDK portalu, a mobilne SDK reklamowe nie mają wersji webowej.
Port rozwiązuje te problemy u źródła. Zostawiamy to, co stanowi o samej grze, a przebudowujemy części, od których zależy jej działanie w przeglądarce.
Codeward: gry na zamówienie, portowanie gier i playable ads
Jesteśmy niewielkim studiem z Krakowa, które założył Paweł Jarosz. Tworzymy gry na zamówienie dla studiów, wydawców i marek, portujemy gry na nowe platformy i robimy playable ads do mobilnych kampanii pozyskiwania graczy. Naszym głównym silnikiem jest Defold. Paweł jest Community & Content Managerem w Defold Foundation i autorem oficjalnego przykładu Defolda dla Poki, więc dobrze znamy ten silnik, także od strony HTML5.
Przenieśliśmy na web wiele gier naszych klientów. W tych projektach wersja w Defoldzie ładowała się szybciej i działała płynniej na słabszych telefonach niż pierwotny build webowy. Techniki, których używaliśmy, można zobaczyć w otwartych projektach podlinkowanych niżej.
Dlaczego do przeglądarki portujemy gry w Defoldzie
Defold to darmowy silnik do gier 2D i 3D z dostępnym kodem źródłowym. Logikę gry pisze się w nim w Lua. Wybieramy go do portów webowych z bardzo praktycznych powodów:
- Mały silnik. W manifeście aplikacji wyłączamy moduły, których gra nie potrzebuje, na przykład fizykę 2D albo wideo. Na stronie z rozmiarami buildów Defolda widać, ile silnik waży na każdej platformie.
- Odroczona zawartość. Dzięki Live Update wyjmujemy poziomy, muzykę i dodatkowe fonty z głównej paczki i pobieramy je dopiero po starcie gry.
- Kompresja tekstur. Profile tekstur w Defoldzie obsługują Basis Universal. W trakcie działania gry taka tekstura jest zamieniana na format, który odczyta GPU danego urządzenia.
- Jeden projekt na wiele platform. Z tego samego projektu w Defoldzie budujemy wersję HTML5, na Androida, iOS, desktop i konsole. Więcej piszemy o tym w artykule o platformach Defolda.
- SDK portali. Przykładowa gra Starbreaker pokazuje Poki SDK w pełnym projekcie w Defoldzie, razem z reklamami i zdarzeniami rozgrywki.
Defold nie pasuje do każdej gry. Grę 3D ze skomplikowanymi shaderami z Unity albo opartą na kilkudziesięciu wtyczkach z Asset Store często lepiej zoptymalizować w Unity, niż przepisywać. Mówimy o tym otwarcie po audycie i wtedy pomagamy poprawić istniejący build.
Portowanie gry z Unity na przeglądarkę
Przy porcie z Unity do Defolda przepisujemy kod rozgrywki z C# na Lua. Sceny i prefaby zamieniamy na kolekcje i obiekty gry. Grafikę, sprite’y i dźwięki przenosimy, zwykle po ponownym eksporcie w takim rozmiarze, w jakim gra naprawdę je wyświetla.
Najwięcej dodatkowej pracy wymagają pakiety. Wtyczki z Asset Store do tweenów, UI, lokalizacji czy reklam trzeba zastąpić odpowiednikiem w Defoldzie albo krótkim własnym kodem. Własne shadery piszemy od nowa jako materiały Defolda w GLSL. Wszystkie te zależności spisujemy już podczas audytu, bo od nich najbardziej zależy czas portu.
Jeśli dopiero wybierasz silnik do kolejnej gry, w porównaniu Defolda i Unity piszemy szerzej o rozmiarze buildów, wydajności i portowaniu.
Portowanie gry z Godota na przeglądarkę
Godot i Defold to lekkie, otwarte silniki, więc port między nimi polega głównie na przełożeniu struktury. Drzewu węzłów ze sceny Godota odpowiadają w Defoldzie obiekty gry z komponentami. GDScript i Lua to dynamiczne języki skryptowe. Logika rozgrywki często zachowuje swój kształt, chociaż każdą linijkę piszemy od nowa.
Z grą z Godota klienci przychodzą do nas zwykle wtedy, gdy eksport webowy jest za ciężki dla wybranych portali albo gra ma działać w przeglądarce na starszych telefonach. Build webowy Godota zawiera cały silnik w pliku WebAssembly, chyba że ktoś skompiluje własne szablony eksportu. W Defoldzie zostawiamy w silniku tylko to, czego gra faktycznie używa.
Sygnały, autoloady i zasoby przenosimy na wzorce znane z Defolda: wiadomości, wspólne moduły Lua i pliki z danymi.
Portowanie z Construct i innych silników
Gry z Construct od początku działają w HTML5, więc port rzadko służy samemu wejściu do przeglądarki. Robimy go, gdy projekt przerósł arkusze zdarzeń, gdy z tego samego kodu mają powstać natywne wersje na telefony albo konsole, albo gdy gra słabo chodzi na tanich telefonach.
Logikę z arkuszy zdarzeń piszemy od nowa w Lua. Animacje sprite’ów pakujemy do atlasów, a layouty zamieniamy na kolekcje i sceny GUI. Kod w zwykłych plikach Lua łatwo trzymać w systemie kontroli wersji i przeglądać każdą zmianę.
Portujemy też gry ze starszych frameworków HTML5, z innych silników i z natywnego kodu na iOS i Androida. Proces opisany niżej wygląda wtedy tak samo.
Co zostaje z oryginału, a co budujemy od nowa
W każdym porcie staramy się wykorzystać jak najwięcej z oryginalnej gry. Gracz ma dostać tę samą grę, tylko szybciej się ładującą.
- Projekt gry, układ poziomów i dane balansu. Pliki poziomów często konwertujemy skryptem, zamiast odtwarzać je ręcznie.
- Grafika i dźwięk, wyeksportowane ponownie w rozmiarach i formatach odpowiednich dla weba.
- Teksty i tłumaczenia.
Od nowa powstaje kod, układ interfejsu pod dotyk i mysz, shadery i efekty, ekran ładowania oraz integracje SDK: reklamy, analityka, zapisy i zdarzenia rozgrywki wymagane przez portal.
Jak wygląda u nas portowanie gry do HTML5
- Audyt. Uruchamiamy obecny build, mierzymy, co pobiera gracz, i spisujemy funkcje silnika, wtyczki i SDK, z których korzysta gra.
- Plan pierwszej minuty. Ustalamy, co musi znaleźć się w początkowym pobraniu, a co może poczekać. Zwykle na starcie potrzebne są menu, samouczek i pierwszy poziom.
- Pierwsza grywalna wersja w przeglądarce. Najpierw portujemy jeden poziom i testujemy go na starszym Androidzie oraz na iPhonie w Safari. Problemy wykryte na tym etapie łatwo poprawić.
- Pełny port. Reszta gry, interfejs i system zapisu.
- Optymalizacja. Kompresja tekstur, atlasy, dźwięk, odroczone ładowanie i odchudzenie silnika.
- Integracja z portalem i testy. SDK Poki albo CrazyGames z reklamami i zdarzeniami rozgrywki, a potem testy w Chrome, Firefoksie, Safari i Edge na komputerze i na telefonach.
- Wydanie. Przygotowujemy build pod portal albo sklep i pomagamy przy premierze.
Dobre praktyki HTML5, które stosujemy w każdym porcie
Większość z nich Paweł zebrał w Starbreakerze, oficjalnym przykładzie Defolda dla Poki. To otwartoźródłowa kosmiczna strzelanka 3D, a w jej kodzie widać każdą z tych technik w prawdziwej grze.
- Odroczone ładowanie z Live Update. Muzyka i fonty dla pisma perskiego, cyrylicy i języków CJK trafiają do osobnego archiwum. Gra pobiera je po starcie i montuje dopiero wtedy, gdy są potrzebne.
- Ładowanie asynchroniczne. Proxy kolekcji ładujemy w tle, kiedy gracz jest jeszcze w menu, więc kolejny poziom czeka gotowy, zanim będzie potrzebny.
- Kompresja tekstur z limitami rozmiaru. W przykładzie atlas UI korzysta z Basis Universal w rozmiarze do 1024 px, a małe tekstury efektów mają limit 256 px.
- Pakowanie tekstur. Sprite’y używane razem trafiają do jednego atlasu. Grafik do późniejszej zawartości nie wkładamy do atlasów pierwszego poziomu, bo inaczej i tak znalazłyby się w początkowym pobraniu.
- Zasoby dopasowane do urządzenia. Telefony dostają lżejsze zestawy tekstur niż komputery, a każdy gracz pobiera fonty tylko dla swojego języka.
- Mniejsze obrazy i dźwięki. WebP w loaderze HTML i na miniaturach, Ogg Vorbis dla dźwięku, efekty w mono i krótkie, zapętlone utwory.
Każdą z tych technik opisujemy krok po kroku, razem z checklistą, w poradniku o optymalizacji gier HTML5.
Testy w mobilnych przeglądarkach
Każdy port testujemy na telefonach już od pierwszej grywalnej wersji. Przeglądarki mobilne różnią się od desktopowych w sposób, który łatwo przeoczyć:
- Sterowanie dotykowe i przyciski na ekranie wygodne dla palca, a do tego obsługa obu orientacji albo czytelna prośba o obrócenie telefonu.
- Dźwięk włączany po pierwszym dotknięciu.
- Pauza, gdy gracz przełączy kartę albo zablokuje ekran, i powrót do gry bez utraty postępu.
- Zużycie pamięci przez całą sesję. Gra, która dobrze startuje, potrafi się wysypać po pół godzinie grania.
Kiedy odradzamy port
Czasem po audycie wychodzi, że gra powinna zostać w swoim silniku. Jeśli build webowy mieści się w limitach portali i dobrze działa na telefonach, lepiej poprawić go na miejscu, niż przepisywać całą grę. Mówimy to, zanim zaczniemy jakiekolwiek prace nad portem.
Porozmawiajmy o przeniesieniu Twojej gry na web
Wyślij nam link do gry albo aktualny build. Napisz, w jakim silniku powstała i gdzie chcesz ją wydać. Przejrzymy ją i odpiszemy, co byśmy zmienili i jak podeszlibyśmy do portu. Skorzystaj z formularza kontaktowego albo napisz na biuro@paweljarosz.pl.
Jeśli Twoja gra powstała z myślą o telefonach, przeczytaj też poradnik o przenoszeniu gry mobilnej do przeglądarki. Opisujemy w nim dystrybucję, sterowanie i webowe SDK od strony produktu.