Warsztat.GDCompo!ProjektyMediaArtykułyQ&AForumOferty pracyPobieranie

Opisz napotkaną sytuację, a redakcja niezwłocznie znajdzie rozwiązanie!

wyślij anuluj

Multiplayer w RTS\ach

Tekst został importowany z Warsztatowych artykułów. Jego oryginalnym autorem jest Tarlandil. Jeżeli został importowany poprawnie, usuń ten szablon!

Wprowadzenie

W związku z pewnymi nieścisłościami w poprzednim arcie o Multiplayerze w RTS'ach, postanowiłem napisać go jeszcze raz.

O czym jest ten art.:
Jest on o sposobie rozwiązania problemu synchronizacji i komunikacji między komputerami, wymagającym stosunkowo małego transferu (w moim projekcie przewidywany wymagany transfer oparty na przedstawionej poniżej metodzie będzie wynosił ok. 4kBps (liczone dla 6 graczy i sieci typu MESH, czyli każdy po równo), oraz umożliwiającym sprawne funkcjonowanie gry nawet przy pingu 500ms (przy większych także może funkcjonować sprawnie, ale to już może być uciążliwe dla graczy - dlaczego o tym później)

O czym NIE jest ten art.:
Nie jest to tutorial czy inny poradnik w stylu "jak przesyłać dane między 2 komputerami za pomącą TCP/IP, UDP, czy IPX.". W tym arcie zakładam że czytelnik ma, potrafi zrobić albo będzie potrafił zorganizować zwykłe połączenie między 2 komputerami oraz że to połączenie będzie sprawne - czyli że protokół bądź programista, gwarantuje, że pakiety nie giną a także że są odbierane w tej samej kolejności w której były wysłane - oczywiście w ramach danego połączenia.

Rozdział 1

Teraz zastanówmy się w jaki sposób można by zrobić taką synchronizację gry dla kilku graczy? Po pierwsze co my będziemy chcieli wysyłać? Nie ma sensu aby np. serwer gry wysyłał co klatkę gry, wszystkim stan całej gry - bo mógłby nawet światłowód nie wystarczyć. W takim razie należałoby wysyłać tylko informacje o zmianach stanu gry, zakładając że wszyscy posiadają na początku gry identyczny stan początkowy. I tutaj można zauważyć że nie ma sensu wysyłać informacji typu " jednostka taka a taka przechodzi na sąsiednie pole, a inna jednostka właśnie strzela do jeszcze innej" bo tych informacji byłaby cała masa. Wystarczy, że będziemy wysyłać tylko te rozkazy które wydaje gracz, gdyż tylko w ten sposób może mieć wpływ na rozgrywającą się grę.

Początek...

W takim razie opieramy się na zasadzie, że jeżeli program, który ma takie same dane, stały kod, zachowa się identycznie. Z tym aby kod był taki sam, nie ma problemu. Co do danych, po pierwsze trzeba zapewnić aby stan początkowy był identyczny na wszystkich komputerach (np. serwer przy starcie gry upewnia się że wszyscy mają to samo i/lub wysyła wszystkim dane które on ma). Teraz jeżeli zapewnimy, że te dane będą ulegały tym samym zmianom w tej samej kolejności na każdym komputerze to sprawa będzie załatwiona - tutaj nie jest ważny w jakim czasie, tylko że w tej samej kolejności.

Synchronizacja

Najprostszym chyba sposobem synchronizacji, jest po prostu co klatkę gry wysyłanie wszystki rozkazów do innych oraz wysyłanie sygnału że to już wszystkie rozkazy. Wtedy jak każdy otrzyma od wszystkich informację od wszystkich, że już wysłali co mieli wysłać w tej klatce to przechodzi do następnej. Coś takiego może zdać jedynie egzamin na LAN'ie ale nie na WAN'ie gdzie pingi mogą być rzędu 500ms.

Więc przedstawię tutaj inny sposób (podobny do tego który jest stosowany w Starkrafcie). Po co nam właściwie synchronizacja co do klatki, wcale jak napisałem powyżej nie jest nam potrzebne aby gry działały identycznie tak samo w czasie, one mają działać tak samo, jedna może trochę wolniej a druga trochę szybciej (byle nie za bardzo - ale o tym później). Więc takie informacje dotyczące synchronizacji mogę być trochę wysyłane znacznie rzadziej.

Rozkazy

A co z rozkazami? No cóż, są dwie możliwości, albo rozkaz będzie wykonywany natychmiast, ale wtedy niestety musimy czekać z następną klatką aż otrzymamy od wszystkich informacje że to już wszystkie rozkazy w tej klatce (gdyż my nie wiemy jak długo pakiety dochodzą do innych - tj. nie mamy nigdy pewności co do tego jakiego czasu pakiet będzie potrzebował na dodatcie). Więc pozostaje nam tylko rozwiązanie, aby rozkazy były przetwarzane dopiero w klatce późniejszej. W takim przypadku np. przed grą, że takie wyprzedzenie będzie wynosić 15klatek. Czyli jak ja jestem w klatce x to jak wysyłam rozkaz na sieć to dołączam do niego informacje o tym, że należy go przetworzyć w klatce x+15. Ja także go przetwarzam w tej klatce. W związku z tym, czołg zacznie jechać dopiero np. za 100ms, 250ms, albo 500ms w zależności od wybranego wyprzedzenia, jeżeli mamy wyprzedzenie 15, a klatek gry 50/s to opóźnienie będzie około 300ms, co nie jest dużo).

Synchronizacja kontratakuje

Wszystko fajnie, ale co by było gdyby jakiś komputer się pospieszył, albo sieć miałaby zastój, i rozkaz, który miał być przetworzony w 152 klatce, dotarł do kogoś kto już jest w 157? Doszłoby do desynchronizacji, u jednych czołg by stał u innych jechał, co w konsekwencji było by katastrofą, gdyż każdy grałby sobie w inną grę. Jak temu zapobiec? Wystarczyłoby mieć pewność, że jak ktoś otrzymuje rozkaz, to jeszcze nie doszedł do tej klatki, a to można uzyskać stosując synchronizację opartą o pozwoleniach. Czyli każdy komputer wysyła co kilka klatek pozwolenie na dojście do klatki taką jaką ma +15. A przejście do następnej klatki jest tylko możliwe jeżeli posiada się pozwolenia od wszystkich. Więc jak moje ostatni o wysłane pozwolenie było np. na klatek 200, to mogę spokojnie nie obawiając się błędów wysyłać rozkazy na klatkę 201. Czyli mamy już co chcemy, po pierwsze nikt nie odbiegnie od nikogo na więcej niż 15 klatek, gra będzie chodziła płynnie, wszyscy będą mieli te same rozkazy w tej samej kolejności, to wszystko tylko kosztem małego opóźnienia w przetwarzaniu rozkazów gracza.

Lecz ktoś uważny zauważyłby że np. mając 4 graczy: 1,2 gracz wysyłają rozkazy na tą samą klatkę, to może zajść coś takiego: gracz 3 otrzymał taką kolejność 1,2 a gracz 4 kolejność 2,1. (Tak samo zresztą gracze 1 i 2, będą mieć inna kolejność). Jak temu zapobiec? Po pierwsze możemy zauważyć, że rozkazy od tego samego gracza będą w dobrej kolejności, więc wystarczy wszystkie rozkazy tuż przed przetworzeniem posortować np. ze względu na numer gracza, jakimś stabilnym algorytmem sortującym.

A jak nie będzie pozwolenia???????

Taka sytuacja świadczy o tym, że albo komuś komp się wiechnął, starsza wyciągnęła wtyczkę z telefonu, lub inne nieszczęśliwe przypadki, typu split sieci. Na to nic poradzić nie możemy i jeżeli taki ktoś nie będzie wysyłał pozwolenia przez pewien czas, to się go wyrzuca z gry informując o tym pozostałych (aby nie doszło do rozsynchronizowania) i gra się dalej bez niego. W przypadku sprawnej sieci (nawet gdy będą ginąć pakiety, ale będziemy w stanie to naprawić), to każdy gracz zanim przebiegnie te 15 klatek, to wysyłając pozwolenia co 5 klatek, wyśle ich co najmniej 2, więc nie ma mowy aby do nikogo nie dotarły. (Wystarczyłoby jedno, ale 2 mają usprawnić połączenie aby nie było tzw. Lagów).

Implementacja

Implementacji jako takiej nie będzie. (Chociaż ja go zaimplementowałem w całości i DZIA£A dobrze, ale to jest niestety część gry). Jeżeli ktoś jest zainteresowany metodą obsługi tych rozkazów i ich przechowywania aż do przetworzenia, to odsyłam do mojego arta o komunikatach.

Tarlandil
14 maja 2002

Tekst dodał:
Adam Sawicki
29.03.2006 21:05

Ostatnia edycja:
Adam Sawicki
29.03.2006 21:05

Kategorie:

Aby edytować tekst, musisz się zalogować.

# Edytuj Porównaj Czas Autor Rozmiar
#1 edytuj 29.03.2006 21:05 Adam Sawicki 7.89 KB
Zwykły
Do sprawdzenia
Do akceptacji
  • Napisz komentarz:
    Aby dodać swój komentarz, musisz się zalogować.
Licencja Creative Commons

Warsztat używa plików cookies. | Copyright © 2006-2017 Warsztat · Kontakt · Regulamin i polityka prywatności
build #ff080b4740 (Tue Mar 25 11:39:28 CET 2014)