HTML5 · Optymalizacja · Defold · Poradnik

Optymalizacja gier HTML5: czas ładowania, rozmiar i wydajność

Żeby zoptymalizować grę HTML5, zmierz, co naprawdę pobiera gracz, a potem zmniejsz początkowe pobranie do minimum: na starcie ładuj tylko pierwszy poziom, a resztę odrocz, kompresuj tekstury i dźwięk, pakuj sprite’y w atlasy, używaj obrazów WebP w odpowiednim rozmiarze i usuń nieużywane funkcje silnika. Potem przetestuj liczbę klatek i pamięć na starszym telefonie. Portale takie jak Poki zalecają początkowe pobranie do 5 MB, bo gracze odchodzą, gdy ładowanie trwa za długo. Ten poradnik omawia każdą technikę na przykładach z otwartoźródłowego przykładu Defolda dla Poki.

· Praktyczny poradnik

Autor:

Read in English →

Defold do gier webowych i produkcji HTML5.

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

  1. Zmierz przesłany rozmiar i czas do pierwszej rozgrywki z wyłączonym cache, na spowolnionym połączeniu i na starszym telefonie.
  2. Sprawdź raport z budowania i wypisz 10 największych zasobów.
  3. Upewnij się, że pierwszy poziom odwołuje się tylko do potrzebnych zasobów.
  4. Przenieś kolejne poziomy, muzykę, opcjonalne postacie i dodatkowe fonty do odroczonego ładowania, z obsługą nieudanego pobrania.
  5. Ustaw kompresję tekstur i maksymalne rozmiary dla grup zasobów.
  6. Pogrupuj sprite’y w atlasy według użycia i przytnij przezroczyste marginesy.
  7. 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ą.
  8. Używaj WebP i obrazów w odpowiednim rozmiarze w szablonie HTML i na ekranie ładowania.
  9. Usuń nieużywane funkcje silnika i włącz kompresję na serwerze.
  10. 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.

FAQ

Pytania o optymalizację gier HTML5

Jaki rozmiar początkowego pobrania jest dobry dla gry HTML5?

To zależy od platformy. Poki zaleca początkowe pobranie do 5 MB i całość do 8 MB. CrazyGames wymaga do 50 MB, a do 20 MB dla mobilnej strony głównej. Mniej zawsze znaczy lepiej, więc ładuj tylko to, czego potrzebuje pierwszy poziom.

Jak zmierzyć prawdziwy rozmiar gry webowej?

Otwórz grę w Chrome z wyłączonym cache w DevTools i sprawdź przesłany rozmiar w zakładce Network. Powtórz pomiar ze spowolnionym połączeniem i na starszym telefonie, a w raporcie z budowania sprawdź największe zasoby.

Czym jest Live Update w Defoldzie?

Live Update pozwala wykluczyć collection proxy albo fabryki z głównego bundla i pobrać ich zawartość później jako archiwum. Służy do odraczania poziomów, muzyki, fontów i innych zasobów, które nie są potrzebne na starcie.

Jakiej kompresji tekstur używać w grach webowych?

W Defoldzie Basis Universal działa na różnych urządzeniach, bo w trakcie działania jest transkodowany do formatu obsługiwanego przez GPU. ASTC daje elastyczną jakość i rozmiar, ale nie każda karta graficzna go obsługuje. Ustaw też maksymalny rozmiar tekstury dla każdej grupy zasobów.

Czy Codeward może zoptymalizować istniejącą grę webową?

Tak. Zaczynamy od audytu buildu i wydajności na urządzeniach docelowych, a potem wdrażamy odroczone ładowanie, kompresję zasobów i poprawki wydajności. Jeśli gra jest za ciężka w obecnym silniku, możemy też przenieść ją do Defolda.

O autorze

Paweł Jarosz jest programistą gier z Krakowa z ponad 13-letnim doświadczeniem, założycielem studia Codeward oraz Community & Content Managerem w Fundacji Defold. Tworzy gry i dzieli się praktyczną wiedzą na kanale Unfolding Gamedev na YouTube.

Twoja gra webowa ładuje się za wolno?

Codeward to studio tworzenia gier z Krakowa, którego główną specjalizacją jest Defold. Optymalizujemy gry HTML5 pod kątem czasu ładowania, rozmiaru i wydajności, przenosimy ciężkie gry z innych silników do Defolda i tworzymy nowe gry webowe i mobilne. Wyślij link do gry albo aktualny build. Odpowiemy najszybciej, jak to możliwe.

Co warto nam wysłać?

  • Link do gry albo aktualny build.
  • Docelowe portale lub platformy i ich limity rozmiaru.
  • Silnik i SDK, z których korzysta gra.
  • Termin i widełki budżetu.