Jak często zapisywać stan gracza w trwałych grach online?


9

W grach online ludzie wolą się logować i wylogowywać, kiedy chcą. Zazwyczaj ich osiągnięcia w grze są bezproblemowo zapisywane na serwerze. Nie jest to trudne do osiągnięcia, ale zastanawiam się, jak można to zrobić w efektywny sposób, który ma sens i daje się skalować.

Czy ma sens zapisywanie współrzędnych gracza i podawanie go za każdym razem, gdy go wysyła? Mój serwer node.js może to zrobić łatwo bez blokowania odpowiedzi i chcę zastosować bazę danych Mongo, ale może bardziej odpowiednie jest to zrobić raz na sekundę, aw przypadku całego serwera, zbierając wszystko naraz?


Zapisuję stan gry co 10 sekund. Myślę, że to wystarczy, pozostanie niezauważone (i uruchamiam mój serwer MMORPG na moim netbooku, który ma 512 MB pamięci RAM).
jcora,

Odpowiedzi:


10

Mam na myśli tradycyjną grę MMORPG, taką jak World of Warcraft.

Oszczędzaj po każdym poleceniu każdego gracza i autonomicznej rzeczy (np. NPC)

  • Stała kopia zapasowa. Serwer może się zawiesić w dowolnym momencie, a stan gry jest zapisywany do tego momentu (a przynajmniej tak niedawno, jak to możliwe).
  • Wpływ na wydajność serwera; nawet jeśli nie blokuje (tj. w innym wątku), nawet jeśli baza danych znajduje się na innym serwerze, przetwarza dane, których inaczej byś nie zrobił. Jeśli nie blokuje, jak mówisz, inny wątek musi sobie z tym poradzić, a to może być zajęty czymś innym.
  • Zwiększona liczba operacji we / wy dysku, a tym samym wzrost ryzyka / wskaźnika awarii. Jest to szczególnie niepokojące, jeśli używasz dysków SSD do przechowywania danych, ponieważ ich żywotność jest krótsza.
  • Jeśli odciążysz bazę danych na inny serwer, zwiększysz przepustowość; może to stanowić problem, jeśli płacisz za przepustowość, a jeśli nie jest to oddzielna karta sieciowa, to zajmuje zasoby, które można lepiej wykorzystać do obsługi ruchu odtwarzacza.
  • Co się stanie, jeśli serwer będzie coraz bardziej opóźniał się w zapisywaniu stanu tych poleceń? Tzn. Jeśli pojawi się więcej poleceń, niż można zapisać, więc układają się w kolejce? Czy ta kolejka przepełnia się i powoduje błąd? Zatrzymujesz wszystko, aby kolejka mogła nadrobić zaległości?
  • Wydaje mi się, że takie podejście, choć wydaje się proste, wymagałoby starannego zaplanowania. Na przykład kolejne polecenia, które polegają na sobie nawzajem, będą musiały zostać zapisane razem; w przeciwnym razie może wystąpić awaria w środku poleceń i tylko jedno zostanie zapisane, ale nie drugie. Zastanów się, czy dwóch graczy wykonuje transakcję, a dwa dyski są zapisywane na dysku: „dodaj 1 element do odbiorcy” i „odejmij 1 element od nadawcy”. Jeśli awaria wystąpi po pierwszym poleceniu, ale przed zapisaniem drugiego polecenia, występuje duplikacja elementu. (jeśli zamówienie zostanie odwrócone, to zgubiłeś przedmiot)

Zapisuj wszystko okresowo

  • W przypadku awarii serwer będzie nieco nieaktualny. Mamy nadzieję, że używasz czegoś w stylu księgowania, więc najnowsza migawka będzie przynajmniej pełna i spójna, a wszyscy aktywni gracze zostaną cofnięci o tę samą ilość czasu.
  • Niezależnie od używanego systemu bazy danych może istnieć optymalizacja aktualizacji wsadowej, która jest bardziej wydajna (mniej narzutów) niż aktualizacja pojedynczo.
  • Jeśli zamiast tego zdecydujesz się na binarny system plików, ta metoda jest bardzo prosta. Utwórz nowy plik, zrzuć do niego pamięć, rzuć na końcu znacznik, który sygnalizuje, że tworzenie kopii zapasowej zostało w pełni ukończone. Po zakończeniu tworzenia jednej kopii usuń poprzednią (lub nie).
  • Proces tworzenia kopii zapasowej może także wymagać uwzględnienia rzeczy wymienionych w ostatnim punkcie wypunktowania w drugiej sekcji, takich jak zapisywanie w środku kolejnych poleceń, których nie należy dzielić. Możesz zablokować cały zestaw danych, zrzucić go na dysk i odblokować, ale w zależności od tego, ile czasu to zajmie, może to spowodować dość mocną pauzę lub spowolnienie w grze.

Zapisz postać podczas wylogowania (nie zapisuj niczego innego)

  • Najważniejszą rzeczą dla gracza jest jego postać, która obejmuje posiadane przedmioty, umiejętności, które zdobył, listę przyjaciół i tak dalej. Jeśli zabiją potwora, a łupy znajdą się na ziemi przed nimi, a serwer zawiedzie, będą mieli trochę złamanego serca, że ​​nie będą mieli okazji odebrać swoich łupów, ale przejdą przez to. Więc po prostu zachowaj ważne rzeczy i nie przejmuj się małymi rzeczami. Nie zapisuj na przykład pozycji NPC; jeśli serwer ulegnie awarii, gdy wróci, odradzają się w ogólnym obszarze, w którym powinni się znajdować. Wyjątkiem są oczywiście wszystkie „inteligentne” postacie niezależne, które z jakiegoś powodu muszą pozostać w miejscu, w którym się znajdują były, gdy serwer przestał działać.
  • Co więcej, gracz nie powinien być zalogowany przez zbyt wiele godzin na raz (zauważ, że rozważam tutaj „powrót do lobby” jako wylogowanie). W końcu będą musieli zrobić sobie przerwę w łazience lub zdobyć jedzenie lub zostać przerwanym przez rodzica / przyjaciela / cokolwiek lub spać. Dlatego naprawdę nie powinni oni logować się bez przerwy dłużej niż, powiedzmy, 8 godzin dla nawet najbardziej zapalonego gracza. Jeśli „gracz” jest zalogowany przez naprawdę długi czas, istnieje duża szansa, że ​​jest to albo wiele osób, albo bot, i żadna z nich nie jest pożądana ani normalna.
  • Ponadto proces wylogowywania powinien już sprawdzać takie rzeczy, jak wyżej wymienione kolejne polecenia. Zasadniczo powinien już spakować postać, więc oczywiście jest to najlepszy czas, aby zrzucić go na dysk.

Zamykanie myśli

  • Oczywiście jestem za ostatnim podejściem, ale starałem się być bezstronny wobec wszystkich trzech.
  • Trudno powiedzieć, która z dwóch pierwszych metod jest bardziej marnotrawna. W przypadku pierwszej metody, jeśli postać wyśle ​​kilka poleceń przesuwania, każda z nich zostanie zapisana na dysku i nadpisana, jeśli wyraźnie można je spakować w jedną. Ale przy drugiej metodzie, jeśli masz wokół siebie połowę populacji, ich pozycje są zapisywane na dysku, nawet jeśli są dokładnie takie same od ostatniej operacji tworzenia kopii zapasowej. W trzecim przypadku jest bardzo możliwe, że ktoś może się zalogować i natychmiast wylogować, ale najczęściej wiele rzeczy w odtwarzaczu ulegnie zmianie, więc marnotrawstwo wydaje się minimalne.
  • Należy pamiętać, że jest to wyłącznie kopia zapasowa w przypadku awarii, a awarię należy całkowicie zminimalizować. Dobrze jest poradzić sobie z tym przypadkiem wyjątku, ale ostatecznie, jeśli serwer ulegnie awarii, niektóre dane zostaną utracone, a niektórzy gracze będą zdenerwowani. Więc po prostu zastosuj dowolną metodę, jaką uważasz za najprostszą lub najlepszą, i kontynuuj.
  • Nie polegaj na tym jako domyślnym zapisie; umieść ładny przycisk zamykania aplikacji serwera, który z wdziękiem zamyka połączenia i zapisuje wszystko do bazy danych. Używaj tego w normalny sposób.

Wreszcie, nie traktuj tej rady jako absolutnej prawdy. Nie napisałem systemu tworzenia kopii zapasowych dla wielu graczy. Pracuję nad „grą” online, dlatego właśnie o tym pomyślałem i napisałem swoje przemyślenia powyżej, ale nie doszedłem jeszcze do etapu implementacji tego. Jest to napisane bez faktycznego doświadczenia, ale po wielu lekturach i zebraniu wiedzy na ten temat.


4
Z tego, co osobiście obserwowałem, komercyjne MMO używają kombinacji wszystkich trzech z nich. Zapisy pojawiają się po ważnych wydarzeniach i działaniach, takich jak zabójstwa bossów / grabieże / handel, okresowo, aby zapobiec pominięciu niekrytycznych działań (i aby nie ukarać tych, którzy są zalogowani przez długi czas) i zawsze po wylogowaniu. Jedna metoda na ogół nie wystarcza. Prawie wszystkie z tych metod opierają się na bazowej bazie danych w stylu SQL, której kopia zapasowa jest przezroczysta i przywracana w przypadku awarii sprzętu.
NtscCobalt

@NtscCobalt - Byłem z tobą do „bazy danych w stylu SQL”. Czy SQL jest naprawdę wymogiem? Co z NoSQL?
beatgammit

@tjameson Cóż, mój komentarz został napisany, zanim dotknąłem NoSQL. Próbowałem tylko powiedzieć, że nie powinieneś rzucać własnym formatem, ale mimo to nadal polecam SQL, ponieważ powinieneś znać schemat przed ręką (lub być leniwym i używać Entity-Key-Value), a spójność jest ważniejsza niż możliwość podziału tych danych na partycje. Aby uzyskać więcej informacji, zobacz stackoverflow.com/questions/7339374/ ...
NtscCobalt

1

Podejrzewam, że zależy to od rodzaju gry i ilości ruchu między graczami a serwerem.

W MMORPG nie ma sensu zapisywanie pozycji graczy za każdym razem, gdy wysyłają informacje do serwera. Bardziej sensowne byłoby aktualizowanie, jeśli bieżące dane odtwarzacza są „nieaktualne”, że tak powiem. Korzystne może być również uratowanie stanu gracza podczas ważnych wydarzeń, takich jak wejście na nowe terytorium, pokonanie bossa lub opuszczenie sklepu.

W grze turowej zdecydowanie warto zapisać stan gracza za każdym razem, gdy kończy swoją turę, a także po turze przeciwnika (oszczędzając utratę zdrowia, efekty zaklęć itp.).

Ponownie, odpowiedź zależy całkowicie od skali i możliwości twojego serwera. Chodzi o znalezienie najlepszej równowagi i optymalizację w jak największym stopniu bez utraty jakości.


1

Jeśli Twoim jedynym zmartwieniem jest to, kiedy się wylogowują, wówczas jedną prostą odpowiedzią jest zapisanie ich pozycji, gdy wystąpią jakiekolwiek warunki dla nich, które już nie istnieją w świecie gry (z powodu wylogowania lub rozłączenia).

Z drugiej strony, byłbym nieco ostrożny wobec klienta zgłaszającego serwerowi swoją pozycję, a przynajmniej bez jakiejkolwiek formy kontroli poczytalności po stronie serwera. Jeśli już to masz, możesz prawdopodobnie zapisać tę pozycję po wylogowaniu lub rozłączeniu, ponieważ nie musisz się martwić o bezpośrednie pobieranie danych od klienta.


Tak, stąd potrzeba regularnego wysyłania aktualizacji do serwera na wartości takie jak pozycja i XP. Im dłużej go zostawiasz, tym bardziej dyskusyjne staje się to, czy gracz rzeczywiście podniósł zgłoszone delty, czy nie. Jeśli ograniczysz te okresy odprawy, znacznie łatwiej będzie monitorować / kontrolować.
Inżynier

Problem z określeniem, kiedy dokładnie gracz wylogował się z długo działającej gry przeglądarkowej, wcale nie jest trywialny.
Lanbo

Zgadzam się, że nie jest to trywialne, ale jest to problem, który musisz rozwiązać w taki czy inny sposób w większości gier, nawet jeśli tylko po to, aby zdecydować, kiedy ich awatar nie będzie już wyświetlany. Gdy to zrobisz, relatywnie prostą sprawą jest podpięcie się do tego scenariusza i zapisanie ostatniej ważnej pozycji.
Lunin,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.