Czy praca developera w sektorze gamedev różni się od pracy w innych gałęziach sektora IT? Jaka jest jej specyfika? Ja po niemal dekadzie pracy w sektorze IT trafiłem do gamedevu i w tym artykule na bazie swojego wystąpienia na konferencji Javeloper we wrześniu 2021 roku, chciałbym opowiedzieć o specyfice tej branży, wyzwaniach i możliwościach, które oferuje.
W Ten Square Games tworzymy gry mobilne w modelu Free2Play, oznacza to, że każdy może pobrać grę bez wstępnych opłat. Nasze gry łatwo zainstalować i można w nie zagrać w każdej chwili – nie jest do tego potrzebny specjalny sprzęt, ani nośnik, wystarczy telefon komórkowy. Dzięki temu, kiedy porównamy nasz produkt do innych produktów IT np. wewnętrznego klienta korporacyjnego, który zleca automatyzację pewnego procesu, w gamedevie o wiele łatwiej jest nam wejść w przysłowiowe buty klienta, co osobiście bardzo cenię.
Choć panuje przekonanie, że gry mobilne to małe gry, to ich skala wcale mała nie jest. W zależności od różnych okoliczności, w danej grze możemy mieć od kilkudziesięciu do kilkuset tysięcy graczy dziennie. Wiąże się z tym pierwsze z wyzwań gamedevu, jakim jest zapewnienie dynamicznej skalowalności produktów.
Wspomniane wyżej liczby, to dla nas bardzo istotne dane i mierzymy je w statystykach nazywanych DAU (daily active users) lub MAU (monthly active users). Z jednej strony to wskaźniki ważne dla biznesu, z drugiej my, po stronie backendu stoimy przed wyzwaniem stworzenia takiej infrastruktury, która pozwoli monitorować dane na dużej populacji graczy w czasie rzeczywistym. Mierzymy naprawdę wiele aspektów gry np. ARPU (average revenue per user), czyli statystyczny przychód, jaki może wygenerować jeden gracz, czy retencję N dniową, wskazującą procent graczy, którzy pozostają w grze dłużej niż N dni i wiele innych.
Kolejnym ważnym aspektem, który musimy wziąć pod uwagę jest zabezpieczenie ekonomii gry. Po pierwsze, żeby w grze nie pojawiła się luka, która może otworzyć furtkę do nieuczciwych praktyk, a po drugie dlatego, że błędy np. w cenach mają dalekosiężne konsekwencje, a naprawa ich skutków to olbrzymia ilość pracy, nie tylko dla jednego zespołu.
Jednym z naszych celów jest zatrzymanie graczy – co w praktyce oznacza, że musimy zapewnić im dobrą zabawę w krótkich cyklach. Aby to osiągnąć, regularnie dodajemy nowe lokacje, wydarzenia, czy funkcjonalności. Nie możemy robić długich przerw serwisowych, bo mamy graczy we wszystkich strefach czasowych. Nie możemy sobie pozwolić na to, aby infrastruktura była przez dłuższy czas niedostępna.
W naszej pracy wykorzystujemy także machine learning. Kryjące się pod tym hasłem rozwiązania analityczne, matematyczne i statystyczne pomagają nam stale dostosowywać ofertę w naszych grach do określonych oczekiwań graczy, tak aby była ona optymalna. Przykładowo decyzja o tym, czy w danej lokacji w Hunting Clash gracze spotykają równocześnie do 3,4 czy 5 zwierząt, jest oparta na zweryfikowanej hipotezie.
Kolejnym wyzwaniem jest stały monitoring i responsywne adresowanie problemów. Aby wychwytywać możliwe problemy na bieżąco, staramy się zdefiniować maksymalnie dużo wskaźników, które monitorujemy w czasie rzeczywistym. Korzystamy z Prometheusa aby wychwytywać dane, a następnie przetwarzamy je w Grafanie i budujemy automatyczne alerty, które mogą być zintegrowane z dowolnym komunikatorem czy pocztą internetową.
Podstawową technologią, z której korzystamy jest Java. Bazujemy na niej całą część serwerową odpowiadającą za warstwę persystencji, komunikacji, warstwę sieciową czy zapewnienie platformy do synchronizacji pomiędzy graczami.
Ze względu na skalę, jednym z wyzwań był wybór bazy danych, która potrafiłaby poradzić sobie z dużym ruchem oraz z łatwością wprowadzania zmian w strukturze danych. Naturalnym kierunkiem okazał się NoSQL, a nasz wybór padł na Redisa, który pozwala na responsywny dostęp do warstwy persystencji.
Oczywiście na potrzeby audytowalności, statystyki czy weryfikacji zgłoszeń graczy, wszystkie akcje graczy są przechowywane w bazach relacyjnych. Procesujemy je z opóźnieniem nieakceptowalnym, aby użyć jej na potrzeby bieżącej sesji gracza.
Używamy również generycznego rozwiązania Netty, które pozwala z małych klocków złożyć nasz protokół, uwzględniający np. możliwość przerywania połączenia, gdy gracz zmienia sieć przykładowo z WIFI na 3G. Netty pozwala też na efektywne wykorzystanie zasobów z użyciem JNI (interfejsu, który pozwala na dostarczenie kodu w języku niższego poziomu), a także na zbudowanie modelu zarządzania pamięcią, który w specyficznym zastosowaniu jest bardziej efektywny niż model oparty o JVM i Garbage Collector
(No) Spring – no magic framework. Kompromis pomiędzy tym czy z małych klocków chcemy złożyć coś mocno specyficznego, czy potencjalnie konfigurować do granic możliwości bardzo ogólny framework, który świetnie się sprawdza w bardziej standardowych zastosowaniach, a dodatkowo zużywa nieco więcej zasobów.
Mimo, że główne serwery gry, które obsługują ruch graczy nie wykorzystują w obecnej architekturze Springa to wiele z naszych usług współdzielonych pomiędzy produktami jest oparta o tą technologię.
Staramy się zawsze zachowywać równowagę pomiędzy prostymi wewnętrznymi rozwiązaniami, które sprawdzają się wystarczająco dobrze, a wyborem generycznych narzędzi, kiedy mogą lepiej i efektywniej zaadresować problem, z którym się mierzymy.
Korzystamy również z powszechnych rozwiązań rynkowych takich jak MQRabbit czy GCP – wiele usług wspierających produkty o innej charakterystyce biznesowej korzysta z innego stosu technologicznego. Jesteśmy otwarci na każde narzędzie, które przyniesie wartość naszym graczom czy deweloperom w codziennej pracy.
Na przedstawionych wykresach szeregów czasowych możemy zobaczyć, jak wygląda ruch w naszych grach. Po lewej stronie widzimy zwyczajny dzień, w którym w pewnym momencie mamy duży wzrostu ruchu. Skąd wynika ten ruch? Czy z dodania nowej zawartości? Czy też pojawił się błąd logowania i gracze wielokrotnie próbowali wejść do gry? Taki wykres jest dla nas zawsze sygnałem, aby to sprawdzić.
Na drugim wykresie widzimy natomiast bardzo duży wzrost. Może być on związany z tym, że gra była dostępna w kilku krajach, aż wreszcie pojawiało się wydanie globalne. Może być to wynik rekomendacji gry pojawiającej się w sklepach Google Play bądź Apple Store, ale równie dobrze, może to być wynik naszych własnych akcji marketingowych. Jednak ten wykres pokazuje, że zawsze musimy być przygotowani na przeskalowanie naszej infrastruktury, czasem z dnia na dzień, tak jak pokazuje ten wykres nawet 10-krotnie. Musi to być więc architektura, która jest rozszerzalna, pozwalając na obsłużenie dużo większego ruchu, kosztem przeskalowania architektury.
Ważnym aspektem tworzenia gier są także zasoby, zarówno nasze, jak i gracza. Obrazując to stwierdzenie przykładem, wyobraźmy sobie sytuację, w której czas ładowania się gry trwa powyżej 10 sekund, lub gdyby gra przy każdym logowaniu w sieci pobierała 2 MB danych. Jak nietrudno się domyślić, takie niedogodności mogą łatwo zniechęcić graczy Podobnie jak większe zużycie baterii, które może być efektem dekompresji danych na urządzeniach końcowych, kiedy chcielibyśmy te dane skompresować zmniejszając transfer. Te niepozorne aspekty mocno przekładają się na wyniki biznesowe gier.
Musimy pamiętać, aby nadmiernie nie obciążać zasobów graczy, równocześnie dbając o zasoby serwerowe. Jeżeli chcemy zapewnić warstwę persystencji, musimy pamiętać, aby tych danych nie było za dużo. Przykładowo, 1 TB nie jest dużą jednostką danych, jednak, jeżeli pomyślimy o pojemności pamięci podręcznej to jest to bardzo dużo.
Dane wymagane w czasie rzeczywistym przechowujemy w szybko dostępnych zasobach – przykładowo w pamięci RAM, na maszynach znajdujących się blisko serwera gry (w sensie topologii sieci). W przypadku relacyjnych baz danych infrastruktura wewnętrzna to przykładowo 50 TB w hurtowni danych, gdzie przechowujemy całą historię aktywności gracza. Informacje jak czy kiedy się logował do gry, w jaki sposób przebiegała jego sesja i w którym momencie odnotowaliśmy największe zainteresowanie rozgrywką.
Wszystkie te dane z jednej strony służą temu, by pomóc graczom, kiedy napotkają problemy i zgłaszają się do naszego działu wsparcia. Przykładowo, kiedy gracz zakupił określony przedmiot w grze, ale z różnych przyczyn go nie otrzymał. Z drugiej strony te informacje pozwalają nam śledzić co udało nam się zrobić dobrze – w którym momencie gry mieliśmy wzrost zainteresowania, co skłoniło gracza do zakupów w grze, jakie wydarzenie sprawiło, że gracze zostali w grze na dłużej. Dzięki temu w kolejnych etapach prac, mamy jasność w jakim kierunku powinniśmy rozwijać dany produkt.
Cała populacja aktywnych graczy jest podzielona na sektory, dana sesja gracza jest obsługiwana kompleksowo tylko przez jeden serwer. Mimo to wszyscy gracze dalej mogą się ze sobą komunikować na poziomie gry.
Podział na serwery jest transparentny dla graczy i pozwala na dynamiczne skalowanie architektury w zależności od ruchu w grze. Używamy HAProxy i od strony serwerowej to jest kwestia jednego klocka w Netty, aby dodać wsparcie dla tej technologii.
W TSG mamy gamę usług wspólnych (tzw. TSG Bar), które wspierają rozwój produktów – narzędzia do AB testowania – Absinthe i inne jak Rum, Whiskey, Martini, Tequilla, Vodka, które dotyczą rozwoju narzędzi dla działu wsparcia technicznego, obsługę kodów rabatowych w grze czy machine learning, który pozwala dostosować zawartość w grze w zależności od profilu gracza.
W budowie architektury takiej jak serwer gry, należy przede wszystkim zadbać, żeby funkcjonalności, które z pozoru są ze sobą powiązane były w kodzie rozbite na niezależne domeny. Logicznego rozbicia na moduły możemy dokonać z wykorzystaniem takich narzędzi jak Maven czy ArchUnit. Ważna jest prawidłowa enkapsulacja i właściwa dekompozycja tak, aby testy jednostkowe były czymś prostym do budowania, a rozwój funkcjonalności mógł się odbywać niezależnie.
Komunikacja o wzorce architektury oparte na event driven development może dość dobrze wyjaśnić jak zapewnić właściwy decoupling na poziomie kodu czy na poziomie różnych usług.
Czym jest model gry? Jest to określona specyfikacja produktu, która zawiera wszystkie istotne parametry dotyczące gry. Takie jak liczba zwierząt dostępnych w grze, czas pojedynku itp. Specyfikacja może być wyrażona w pewnym metajęzyku np. XML czy JSON, a serwer jest interpreterem tej specyfikacji. Na podstawie takiego modelu dostarczamy graczom rozrywkę. Model może zawierać elementy zmienne, które definiują zadania na dany dzień czy wyzwania, z którymi gracz musi się zmierzyć w rywalizacji danego dnia. Ważne dla nas jest to, abyśmy mogli w łatwy sposób konfigurować rozgrywkę i dać zespołom budującym grę możliwość zaskakiwania użytkowników nową zawartością, bez konieczności kosztownej aktualizacji gry na sklepie.
Chcemy, aby Game Designerzy mieli możliwość tworzenia logiki gry w sposób niepowiązany z logiką serwerową. Dlatego udostępniamy dany metajęzyk, będący reprezentacją modelu gry. Np. nasi projektanci tworzą obiekty, które reprezentują wydarzenia – elementy rywalizacyjne gry czy nowe lokacje i wyrażają to w pewnych strukturach. My jako twórcy rozwiązań serwerowych i produktowych tworzymy rozwiązania używając tego samego języka. Dzięki takiemu podejściu, razem z Game Designerami tworzymy model, który buduje nasz język domenowy. Jest on podejściem DDD (Domain Driven Development) i pozwala budować wspólny język między zespołami.
Często stajemy przed pytaniem, w jakim kierunku rozwijać grę? Mogą to być proste kwestie, jak to ile zwierząt na planszy widzi gracz podczas rozgrywki, po zagadnienia retencji. Dlatego stosujemy sporo testów A/B, aby nasze decyzje były poparte danymi.
Z jednej strony mamy pewną specyfikację modelu, z drugiej serwer, który pozwala interpretować ten model, co stawia przed deweloperami sporo wyzwań. Wyobraźmy sobie, że twórcy gry chcą dodać nowy obiekt, a przed nami pojawia się pytanie – jak komunikować graczom to, że w grze ma miejsce nowe wydarzenie?
Przykładowe wyzwania techniczne, z którymi możemy się spotkać to:
Trzeba pamiętać, że ze względu na globalną skalę produktu, nasza infrastruktura musi być dostępna przez 99,99% czasu. Chcemy zminimalizować konieczność pobierania nowej zawartości gry w sklepie, ponieważ może to prowadzić do zwiększonej retencji graczy. Rozwiązania, które stosujemy zakładają, że będziemy mogli dokładać do gry stale nową zawartość, a zarazem zredukować konieczność aktualizacji.
Poniżej na diagramie mamy przykłady naszych możliwości dodawania nowej zawartości do gry. Warto podkreślić, że naszym celem jest zminimalizowanie liczby aktualizacji gry, a z drugiej strony stałe zaskakiwanie graczy nową zawartości, potencjalnie przy każdej sesji.
Dlatego mamy różne możliwości dodawania nowej zawartości:
Pozornie gry mobilne wydają się być proste. Jednak, jak widać pod kątem wyzwań technologicznych, tego jak adresujemy dane problemy i tego, jakie mamy cele, są one w pełni profesjonalną gałęzią sektora IT, w której podążamy za rynkiem i tworzymy innowacyjne produkty. Co więcej to branża, która pozwala bardzo szybko zwalidować czy dane rozwiązanie się sprawdza, czy nie, a dodatkowo daje dużą łatwość, aby poczuć się jak użytkownik naszego produktu.
Czy łatwo wejść do branży gamedev? Myślę, że nie jest to trudne, a patrząc z perspektywy backend developera, trzeba na to spojrzeć jak na kolejną domenę, w której pracujemy i która ma swoje specyficzne reguły i sposób pracy.
Więcej o prawdach i mitach związanych z tą branżą znajdziecie w naszym wpisie Gry mobilne – prawdy i mity o branży mobile gamedev.
A jeśli sam chcesz przekonać się, jak pracuje się w gamedevie, zobacz, jakie mamy obecnie dostępne oferty pracy.
Damian Dudek, Backend Development Lead – budowniczy systemów IT w gamedevie. Studia matematyczne pozwoliły zbudować mu fundamenty warsztatu, który od dekady wykorzystuje w świecie IT. Każdy nowy projekt czy wyzwanie programistyczne wymagają od niego pozyskiwania nowych narzędzi, tj. technologii czy języków programowania. Gdy nie pracuje przy komputerze, chętnie wybiera się na wyprawy górskie – te krótsze w Sudety lub dalsze – na krańce Europy.
Często, nazywane prześmiewczo “kiblówkami”, gry na urządzenia mobilne kojarzą się z grami “na chwilę”, łamigłówkami,…
czytaj więcejJedną z pięciu wartości – drogowskazów naszej pracy w Ten Square Games jest #Grow Together.…
czytaj więcejHunting Clash to gra myśliwska, która światową premierę miała w drugiej połowie 2020 r., i…
czytaj więcejHunting Clash to nasza gra myśliwska, która w niedługim czasie dotarła do 152 pozycji w…
czytaj więcej