Jak mogę przypisać identyfikatory jednostek w solidny sposób w grze sieciowej?


17

Pracuję nad systemem jednostek dla gry sieciowej i przypisuję każdej jednostce unikalny 32-bitowy identyfikator liczby całkowitej, którego mogę użyć do serializacji odniesień do jednostek i samych jednostek.

Obecnie tylko zwiększam licznik za każdym razem, gdy tworzony jest byt. Wydaje mi się, że identyfikatory ostatecznie się skończą, ale tak naprawdę nie spodziewam się posiadania 4 miliardów podmiotów. Pozwala to również uniknąć problemu, jeśli jednostka 5 zostanie zniszczona, a otrzymamy identyfikator 5. Czy ma to oznaczać odniesienie do nowego # 5 lub starego usuniętego # 5?

Problem polega na tym, że nie jestem pewien, jak radzić sobie z kolizjami / unikać ich. Obecnie, jeśli klient otrzyma aktualizację dla podmiotu o identyfikatorze wyższym niż jego obecny „darmowy identyfikator”, po prostu podbija swój darmowy identyfikator aż do przeszłości. Ale to nie wydaje się bardzo solidne.

Myślałem o przypisaniu zakresów każdemu klientowi, aby mogli oni alokować jednostki bez konfliktu (powiedzmy, że górne n bitów to liczba graczy), ale martwię się, co się stanie, jeśli zakresy zaczną się nakładać z czasem.

Czy istnieje lepszy sposób na poradzenie sobie z tym? Czy powinienem nawet przejmować się przepełnieniem identyfikatorów lub przekroczeniem dozwolonego zakresu? Mógłbym dodać kod, aby wykryć te przypadki, ale co by zrobił, gdyby zdarzyły się inaczej niż awaria.

Inną opcją jest użycie czegoś o większej szansie bycia wyjątkowym, takiego jak 128-bitowy identyfikator GUID, ale wydaje się to bardzo ciężkie w przypadku gry, która próbuje zminimalizować ruch w sieci. Ponadto, realistycznie, nigdy nie potrzebowałbym więcej jednostek naraz, wtedy zmieściłby się w 32-bitowej lub nawet 24-bitowej liczbie całkowitej.

Dzięki!


1
Dlaczego nie wszyscy klienci mają te same podmioty? Czy klienci nie są zsynchronizowani? A może jest to jakiś duży świat, w którym klienci nie prowadzą tej samej gry.
Philip

2
Moja architektura jak dotąd luźno podąża za wersją UE3 (więcej informacji tutaj ). Zasadniczo klienci wiedzą tylko o podmiotach, które są blisko nich na świecie. Ponadto klienci nie działają w trybie blokowania, ale serwer kontroluje większość logiki i może w dowolnym momencie zastąpić dane klienta. Wydaje mi się, że teraz, gdy o tym myślę, mógłbym jedynie zezwolić serwerowi na tworzenie encji i zmuszanie klientów do korzystania z RPC. Nie jestem pewien najlepszego podejścia. Z zawodu jestem programistą graficznym :)
Lucas

1
Myślę, że, jak mówisz, powinien być obsługiwany tylko przez serwer, jeśli jest to w ogóle wykonalne w ramach danej architektury. Następnie trzymaj stos bezpłatnych identyfikatorów encji, który istnieje osobno od listy / mapy encji, abyś wiedział, jakie identyfikatory są dostępne. Niepowodzenie autorytatywnego modelu serwera, więc podejście dystansowe powinno działać dobrze, jeśli chodzi o zakresy. Cztery miliardy to dużo, nawet do podziału między 4000 graczy w MMO. Następnie zastosuj to samo podejście, aby śledzić dostępne identyfikatory, jak w przypadku autoryzacji. serwer.
Inżynier

@Lucas, twój link mówi „Serwer identyfikuje zestaw„ odpowiednich ”aktorów dla każdego klienta”. Oznacza to, że serwer wie o wszystkich podmiotach i jest w stanie je wyliczyć.
Kylotan

1
Jasne, ale co jeśli klient utworzy nowy byt A, ale zanim będzie mógł uzyskać komunikat o utworzeniu, serwer utworzy nowy byt B, obaj otrzymają ten sam „darmowy” identyfikator.
Lucas

Odpowiedzi:


13

To, co zrobiłem, sprawia, że ​​serwer robi wszystko . Klient (klienci) mogą po prostu poprosić serwer o zrobienie czegoś, ale sami nie mogą nic zrobić. W takim przypadku serwer zawsze będzie przypisywać identyfikatory i rozwiązać problem.

Nie miałem do czynienia z prognozami po stronie klienta, czekając, aż serwer zatwierdzi działania takie jak: „Wystrzel rakietę” lub „Zrób tutaj stację słoneczną”. Te akcje będą chciały tworzyć encje, a encje mają identyfikatory. Do tej pory po prostu siedzę na kciuku i czekam na serwer, ale uważam, że to, co należy zrobić, to utworzyć tymczasowy byt podczas oczekiwania na zatwierdzenie serwera. Po otrzymaniu zatwierdzenia serwera serwer przypisze identyfikator i możesz zaktualizować lub zastąpić obiekt tymczasowy.

Ja również nie miałem do czynienia z przepełnieniem identyfikatora, ale jeśli serwer ma pełną kontrolę i wykryje przepełnienie, może wykonać dowolną obsługę, którą uznasz za niezbędną (uruchom ponownie przy 0, wybierz z wolnego stosu, awarii itp.) I wszystkie klienci nawet nie będą wiedzieć ani się tym przejmować. Klienci akceptują tylko identyfikatory wręczone przez serwer.


Dzięki za wszystkie dobre informacje chłopaki! Skończyło się na tym, że serwer tworzy podejście do wszystkich bytów, ale jeśli okaże się, że wprowadza to zbyt duże opóźnienie, wypróbuję metodę Trevora.
Lucas,

W przypadku identyfikatorów specyficznych dla klienta (potrzebnych do przewidywania podczas oczekiwania na serwer) można po prostu użyć prefiksu w identyfikatorze.
danijar

6

Kiedy zrobiłem to w komercyjnej grze wieloosobowej, zrobiłem dokładnie to, co proponujesz: użyj 32-bitowej liczby całkowitej GUID, w której osiem górnych bitów to numer gracza, a dolne dwadzieścia cztery bity zawierają lokalnie unikalny numer.

Jeśli / kiedy nastąpi przepełnienie numeru lokalnego (w moim przypadku prawie nigdy by się to nie zdarzyło; przy normalnym użytkowaniu zajęłoby to od czterech do pięciu dni ciągłego odtwarzania w jednej sesji sieciowej, aby to się stało), właściciel wyśle Komunikat „Resetuj wszystkie moje obiekty” i przenumeruj wszystkie wciąż istniejące obiekty, zaczynając od zera. Wiadomość kazała wszystkim partnerom odrzucić otrzymane obiekty i ponownie zapytać o nie.

Bardziej wymyślnym podejściem byłby komunikat „Obiekt z GUID 'n' to teraz Obiekt z GUID 'm'” dla każdego istniejącego obiektu. Ale w moim przypadku było to mało prawdopodobne i nie sądziłem, że ludzie będą mieli coś przeciwko odległym obiektom znikającym ze świata na pół sekundy, po pięciu dniach nieprzerwanej gry w jednej sesji sieciowej. ;)


To dobry pomysł na radzenie sobie z przepełnieniem. Proste, ale nie myślałem o tym :). „Zapominanie” wszystkich twoich bytów jest miłe, ponieważ może w zasadzie ponownie użyć tej samej ścieżki kodowej, z której korzysta klient, gdy dołącza do gry
Lucas,

4

Jeśli Twoi klienci mogą odrodzić swoje własne istoty, domyślam się, że masz grę wieloosobową peer-to-peer.

W takim przypadku prawdopodobnie nie masz zbyt wielu klientów. Na pewno nie więcej niż 256. I gwarantujemy, że twój identyfikator podmiotu zmieści się w 24 bitach (16000000+ podmiotów wystarczy dla wszystkich!). Więc po prostu ustaw najwyższy bajt swojego identyfikatora na identyfikator klienta:

entityId = clientId<<24 + (maxEntityIn++)

lub coś.

A jeśli się mylę i masz wiarygodny serwer, nigdy nie twórz nowych podmiotów na klientach.


1

Używam metody „najbardziej naiwnej” (po prostu zwiększam liczbę całkowitą dla każdego nowego ID) w mojej trwałej grze wieloosobowej i działa dobrze, ponieważ nie pozwalam klientowi tworzyć nowych ID: s.

Jeśli pozwolisz klientowi zdecydować (stosując wyjaśnienie techniki GUID), klient może również wprowadzić różne błędy, przypisując Stary identyfikator do nowego elementu (to właśnie wymyśliłem na głowie, myśląc, że to 5 sekund , może być wiele innych luk).

Jak zwykle, aby zapobiec oszukiwaniu , serwer powinien WSZYSTKO tworzyć i sprawdzać poprawność .

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.