Dlaczego czas ładowania decyduje o sukcesie gry webowej
Gra webowa nie ma etapu instalacji, który zobowiązuje gracza do zostania. Gracz klika miniaturkę, czeka i albo zaczyna grać, albo przechodzi do następnej gry. Każda sekunda ładowania to sekunda, w której może zmienić zdanie.
Dane z szerszego internetu pokazują, jak bardzo ludzie nie lubią czekać. Według danych Google z 2016 roku 53% wizyt na stronach mobilnych kończy się porzuceniem, jeśli strona ładuje się dłużej niż trzy sekundy. Raport Google Milliseconds Make Millions dodaje, że gdy czas ładowania rośnie z 1 do 3 sekund, prawdopodobieństwo odrzucenia strony rośnie o 32%, a z 1 do 5 sekund o 90%. Te badania dotyczyły stron internetowych, nie gier, ale portale z grami webowymi opisują to samo zachowanie:
- Poki zaleca, żeby początkowe pobranie gry webowej nie przekraczało 5 MB, a całość 8 MB. W wymaganiach Poki zaznacza, że gracze zwykle przechodzą do innej gry, jeśli ładowanie trwa dłużej niż 10 sekund.
- CrazyGames wymaga początkowego pobrania do 50 MB, a do 20 MB, jeśli gra ma trafić na mobilną stronę główną. W poradniku startowym portal podaje, że najlepsze tytuły zwykle ładują się w mniej niż 10 sekund i mają build mniejszy niż 20 MB.
- Facebook Instant Games, jak podsumowuje podręcznik Defolda o optymalizacji rozmiaru, powinny startować w mniej niż 5 sekund, a najlepiej w mniej niż 3 sekundy.
W Codeward optymalizujemy gry HTML5 w wielu projektach dla klientów: zarówno gry, które tworzymy od zera, jak i gry portowane z innych silników. Poniżej opisuję techniki, które za każdym razem dają największą różnicę. Większość przykładów dotyczy Defolda, ale zasady działają w każdym silniku.
Najpierw pomiar: co naprawdę pobiera gracz?
Optymalizacja zaczyna się od pomiaru, a nie od zgadywania. Rozmiar folderu z buildem na dysku to nie to samo, co pobiera gracz: serwery kompresują pliki, a przeglądarki je cache’ują. Otwórz grę w Chrome, wyłącz cache w DevTools i sprawdź w zakładce Network łączny przesłany rozmiar i czas do pierwszej grywalnej klatki. Powtórz pomiar z ograniczeniem przepustowości, żeby zasymulować wolniejsze połączenie mobilne, i na co najmniej jednym starszym telefonie.
Potem sprawdź, co zawiera build. W Defoldzie raport z budowania pokazuje każdy zasób i jego rozmiar, więc od razu widać, które tekstury, dźwięki albo fonty ważą najwięcej. Portale mierzą moment, w którym gracz faktycznie może grać: CrazyGames liczy na przykład początkowe pobranie do pierwszego zdarzenia rozpoczęcia rozgrywki wysłanego przez SDK, a nie do końca paska ładowania.
Projekt referencyjny: przykład Defolda dla Poki
Żeby pokazać te techniki w kompletnej grze, stworzyłem Starbreaker, oficjalny przykład Defolda dla Poki. To otwartoźródłowa strzelanka kosmiczna 3D z misjami, sklepem, ustawieniami, integracją Poki SDK i wbudowanym poradnikiem z wskazówkami dla twórców gier webowych. Jej konfiguracja to dobra mapa tego, co warto optymalizować:
- Live Update z osobnym archiwum ZIP. Fonty dla języka perskiego, cyrylicy i języków CJK oraz muzyka są umieszczone w wykluczonych collection proxy. Trafiają do osobnego archiwum Live Update, które pobiera się po starcie gry i montuje dopiero wtedy, gdy jest potrzebne.
- Bezpieczna obsługa błędów. Loader odroczonych zasobów obsługuje nieudane pobranie: gra działa dalej z domyślną zawartością i może spróbować ponownie później, więc utrata połączenia nigdy nie blokuje pierwszego poziomu.
- Profile tekstur. Atlas interfejsu korzysta z kompresji Basis Universal i maksymalnego rozmiaru 1024 pikseli, a małe tekstury efektów są ograniczone do 256 pikseli.
- Mniejszy silnik. App manifest usuwa moduły silnika, których gra nie używa, takie jak fizyka 2D, dekoder WAV i wideo, a nagrywanie dźwięku i wczytywanie obrazów zastępuje pustymi zaślepkami.
- Szybki start w przeglądarce. Włączony jest streaming WebAssembly, ukryte są baner „Made with Defold” i przycisk pełnego ekranu, a własny loader HTML pokazuje postęp.
- Skompresowane audio. Wszystkie dźwięki i muzyka są w formacie Ogg Vorbis, a utwory muzyczne to skompresowane wersje oryginałów.
Wskazówki w grze ujmują to prosto: wszystko, do czego odwołuje się atlas, kolekcja albo fabryka, trafia do początkowego pobrania, nawet jeśli jest ukryte albo nieużywane na początku.
Odroczone ładowanie: podziel grę na to, co potrzebne teraz i później
Najskuteczniejsza technika to pobieranie tylko tego, czego potrzebuje pierwsza minuta gry. Poradnik Poki o onboardingu nazywa progresywne ładowanie jedną z najważniejszych technik sukcesu w sieci: najpierw pobierz menu, tutorial i pierwszy etap, a resztę ściągaj w tle, gdy gracz już zaczyna grać.
W Defoldzie służy do tego Live Update. Oznaczasz collection proxy albo collection factory jako wykluczone, a ich zawartość trafia z głównego bundla do archiwum, które hostujesz obok gry. W trakcie działania gry pobierasz i montujesz archiwum, a potem asynchronicznie ładujesz proxy.
- Zacznij od pierwszego poziomu. Kolekcja startowa i pierwszy poziom powinny odwoływać się tylko do zasobów, których potrzebują.
- Odrocz zawartość opcjonalną. Dobrzy kandydaci to kolejne poziomy, odblokowywane postacie, skórki, utwory muzyczne i fonty dla innych języków.
- Ładuj w tle. Zacznij pobieranie, gdy gracz jest w tutorialu albo w menu, żeby zawartość była gotowa, zanim będzie potrzebna.
- Zaplanuj błędy. Nieudane pobranie powinno skończyć się domyślną zawartością, czytelnym komunikatem i możliwością ponowienia.
Inne silniki mają swoje odpowiedniki, na przykład Addressables w Unity albo zewnętrzne pliki PCK w Godocie, jak opisują wskazówki CrazyGames o ładowaniu.
Tekstury: kompresja, rozmiar i atlasy
Grafika to zwykle największa część gry webowej 2D, a tekstury zajmują też pamięć GPU, co ma znaczenie na tanich telefonach.
- Kompresja tekstur. Profile tekstur w Defoldzie obsługują Basis Universal i ASTC. Basis Universal jest w trakcie działania transkodowany do formatu obsługiwanego przez GPU urządzenia, więc jeden plik działa na różnych urządzeniach. ASTC oferuje bloki od 4×4 do 12×12 tekseli, czyli od 8 do 0,89 bita na teksel, ale nie każda karta graficzna go obsługuje.
- Maksymalny rozmiar w profilu. Ustaw maksymalny rozmiar tekstury dla każdej grupy zasobów. Tło może wymagać dużej tekstury, ale ikony, cząsteczki i efekty rzadko.
- Właściwa rozdzielczość źródła. Eksportuj grafikę w rozmiarze, w jakim faktycznie jest wyświetlana. Obrazek rysowany na ekranie w 200 pikselach nie potrzebuje źródła w 2048 pikselach.
- Mipmapy tylko tam, gdzie trzeba. W interfejsie 2D wyświetlanym zawsze w tej samej skali mipmapy zwiększają zużycie pamięci, a nie poprawiają jakości.
Texture packery i atlasy
Pakowanie sprite’ów w atlasy zmniejsza liczbę plików do pobrania i liczbę przełączeń tekstur podczas renderowania, co pomaga utrzymać małą liczbę draw calli.
- Grupuj według użycia. Trzymaj w jednym atlasie sprite’y używane razem, na przykład jeden atlas dla interfejsu, jeden dla pierwszego poziomu i osobne dla późniejszej zawartości. Atlas używany przez odroczoną zawartość nie może być wskazywany przez główny bundle, bo i tak zostanie pobrany na starcie.
- Przycinaj przezroczyste marginesy. Packery potrafią obciąć puste brzegi i ciasno upakować grafiki, co oszczędza miejsce w grach z dużą liczbą sprite’ów.
- Unikaj gigantycznych atlasów. Jeden ogromny atlas ze wszystkim zmusza gracza do pobrania grafiki z poziomów, do których może nigdy nie dojść.
Zewnętrzne narzędzia, takie jak TexturePacker, przygotowują arkusze sprite’ów dla silników, które nie pakują atlasów automatycznie.
Obrazy poza silnikiem: WebP i skalowanie
Ekran ładowania, szablon HTML, ikona gry i miniaturki do sklepów lub portali są pobierane, zanim silnik wystartuje, więc też się liczą.
- Używaj WebP w szablonie HTML i na ekranie ładowania, a wersję zapasową trzymaj tylko wtedy, gdy wymagają tego docelowe przeglądarki.
- Skaluj przed eksportem. Zmniejsz obrazy do największego rozmiaru, w jakim są wyświetlane, zamiast liczyć na to, że przeglądarka je pomniejszy.
- Lekki ekran ładowania. Logo i proste tło wystarczą. Ekran ładowania nie powinien być zauważalną częścią pobrania.
Audio: ukryty ciężar
Dźwięk często zajmuje więcej miejsca, niż się wydaje, zwłaszcza muzyka.
- Używaj formatów skompresowanych. Komponent dźwięku w Defoldzie obsługuje WAV i Ogg Vorbis. Używaj Ogg do muzyki i dłuższych efektów, a WAV zostaw tylko dla bardzo krótkich dźwięków, jeśli naprawdę pomaga.
- Krótka muzyka w pętli. Wskazówki w przykładzie dla Poki zalecają krótką, zapętlaną muzykę. Jedna dobrze zrobiona pętla jest lepsza niż kilka długich utworów w początkowym pobraniu.
- Mono, gdzie się da. Większość efektów dźwiękowych nie potrzebuje stereo. CrazyGames też zaleca audio w formacie Vorbis i wymuszanie mono, gdzie to możliwe.
- Odrocz muzykę. Ładuj muzykę po pierwszej interakcji, tak jak w przykładzie dla Poki, żeby gra szybciej stała się grywalna.
Zasoby dla różnych urządzeń i rozmiar silnika
Nie każdy gracz potrzebuje tych samych plików. Telefon z małym ekranem nie potrzebuje tekstur przygotowanych na duży monitor, a gracz czytający po angielsku nie potrzebuje fontów do japońskiego.
- Warianty dla urządzeń. Przygotuj lżejsze zestawy tekstur dla urządzeń mobilnych, a cięższy zestaw ładuj tylko na desktopie, albo wybieraj wariant przy starcie na podstawie rozmiaru ekranu.
- Fonty dla języków. W głównym bundlu umieść fonty dla domyślnego języka, a fonty dla innych alfabetów ładuj przez Live Update, tak jak przykład dla Poki robi to z perskim, cyrylicą i CJK.
- Usuń nieużywane funkcje silnika. W Defoldzie app manifest pozwala wykluczyć biblioteki silnika, których gra nie używa. Wykres rozmiaru buildów Defolda pokazuje rozmiar silnika dla każdej platformy i wersji.
- Kompresja na serwerze. Upewnij się, że serwer wysyła pliki gry z kompresją gzip albo Brotli. CrazyGames zaleca Brotli dla eksportowanych plików.
Wydajność na słabszych urządzeniach
Mały build, który przycina, to nadal złe pierwsze wrażenie. Wskazówki w przykładzie dla Poki zalecają budowanie HTML5, testy w przeglądarce i uwzględnienie w testach starszego lub słabszego urządzenia. Celem jest stabilne tempo klatek, mała liczba draw calli i brak rosnącego zużycia pamięci w trakcie sesji.
- Profiluj przed optymalizacją. Znajdź element, który kosztuje najwięcej, i uprość go jako pierwszy.
- Używaj obiektów ponownie. Tworzenie i usuwanie wielu obiektów w każdej klatce powoduje skoki garbage collectora, więc używaj ponownie pocisków, cząsteczek i efektów.
- Pilnuj draw calli. Atlasy, mniej materiałów i mniej nakładających się przezroczystych warstw utrzymują małą liczbę draw calli.
- Ograniczaj częstotliwość aktualizacji. Nie każdy system musi działać w każdej klatce.
Checklista optymalizacji HTML5
- Zmierz przesłany rozmiar i czas do pierwszej rozgrywki z wyłączonym cache, na spowolnionym połączeniu i na starszym telefonie.
- Sprawdź raport z budowania i wypisz 10 największych zasobów.
- Upewnij się, że pierwszy poziom odwołuje się tylko do potrzebnych zasobów.
- Przenieś kolejne poziomy, muzykę, opcjonalne postacie i dodatkowe fonty do odroczonego ładowania, z obsługą nieudanego pobrania.
- Ustaw kompresję tekstur i maksymalne rozmiary dla grup zasobów.
- Pogrupuj sprite’y w atlasy według użycia i przytnij przezroczyste marginesy.
- Przekonwertuj muzykę i dłuższe dźwięki do Ogg Vorbis, używaj mono, gdzie się da, i trzymaj muzykę krótką i zapętloną.
- Używaj WebP i obrazów w odpowiednim rozmiarze w szablonie HTML i na ekranie ładowania.
- Usuń nieużywane funkcje silnika i włącz kompresję na serwerze.
- Przetestuj liczbę klatek i pamięć na starszym telefonie podczas pełnej sesji.
Jak może pomóc Codeward
Stosowaliśmy te techniki w wielu projektach dla klientów, od nowych gier webowych po istniejące gry mobilne przenoszone do przeglądarki, i za każdym razem skracały czas ładowania i poprawiały płynność. Zwykle zaczynamy od audytu obecnego buildu: co pobiera gracz, co można odroczyć i co spowalnia grę na słabszych urządzeniach. Potem wprowadzamy zmiany i mierzymy wynik na Twoich urządzeniach docelowych.
Jeśli Twoja gra powstała w innym silniku i jest za ciężka na web, lepszym rozwiązaniem może być przeniesienie jej do Defolda. Przeczytaj nasz poradnik o portowaniu gry mobilnej do przeglądarki, porównanie Defold czy Unity do gier webowych i mobilnych oraz artykuł o Defoldzie do gier HTML5. Możesz też wysłać nam link do swojej gry do wstępnej oceny.