XNA/C# - síťová hra - jak funguje predikce? – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

XNA/C# - síťová hra - jak funguje predikce? – .NET – Fórum – Programujte.comXNA/C# - síťová hra - jak funguje predikce? – .NET – Fórum – Programujte.com

 

Eflyax0
Duch
7. 11. 2012   #1
-
0
-

Ahoj, rozhodl jsme se si udělat v XNA síťovou RPG hru. Během nějaké doby se mi to podařilo - mám server, přes který komunikují klienti. Problém mám ale s latencí - to nevím, jak vyřešit. V lokální síti vše šlape jako hodinky - z 98% v reálném čase (ping 0-1ms). Pokud dám ale server na server s veřejnou IP adresou a hraje se přes internet (ping 28-32ms), je vše výrazně zpomalené.  Zatím jsem to nějak neřešil, ale jednou budu chtít mezi hráči dělat třeba souboje a takhle to nepůjde...

Už jsem o tom přečetl hodně článků (převážně v angličtině) ale nikde to není pěkně vysvětlené. Potřeboval bych nějaký teoretický rozbor, jak udělat tu predikci (předvídání) - kód, nepotřebuji, naprogramuji si to sám. Potřebuji to akorát vysvětlit, jak to funguje.

Jak to mám třeba udělaný pohyb postav?

Klient na server odesílá 5x za sekundu, všechny vlastnosti svojí postavy (její souřadnice, otočení, atd..). Server tuto zprávu přijme a rozešle to všem hráčům. Ostatní klienti tuto zprávu přijmou a nastaví tyto parametry u daným objektům (hráčům). Narazil jsem tu ale na problém - tyto data nechodily plynule, a tak postavičky při chůzi lagovaly. Dal jsem tedy postavám ještě jedny souřadnice (virtuální) které ve skutečnosti odesílají (ne svou pozici) a po příchodu dat do cizího klienta se pak každá postavička snaží dohonit tyto své virtuální souřadnice - chodí tedy plynule, ale opožděně. 

Jak mám pak řešit útoky? Kouzla? Ostatní to uvidí pozdě...

U kouzel mě napadlo to, že než postava kouzlo vyvolá (např.: letící ohnivou kouli) tak ihned odešle ostatním info, že kouzlo vyvolala a začne provádět tzv. casting (vyvolávání kouzla), což bude nějaký animovaný efekt - během kterého bude info o vyvolaném kouzle putovat do ostatních klientů. Po pár milisekundách to všem dorazí, a oni u sebe okamžitě zobrazí ohnivou letící kouli letící od mé postavy. V tu chvíli se u mě zastaví vyvolávání kouzla (casting) a já také vypustím tu kouli. Bude tedy u všech zobrazena zhruba ve stejný čas... Jiné řešení mě nenapadá....

Poradil by mi tedy někdo, jak toto funguje v jiných hrách? Jak mám spočítat tu latenci, aby se to u všech zobrazilo stejně?

Děkuji za jakékoliv postřehy a nápady.

Nahlásit jako SPAM
IP: 213.192.34.–
Mutagen0
Super člen
7. 11. 2012   #2
-
+1
-
Zajímavé

#1 Eflyax
Asi nemam do toho moc co mluvit nejsem vubec zdatnej v programovaní her a už vubec ne online her, ale taky bych si jednou chtěl něco lehkýho naprogramovat ale to jsem odbočil. Taková otázka není trošku víc zbytečný posílat každou sekundu 5x informace na server? Podle mě by bylo lepší kdyby jsi na to udělal nějakou událost a jakmile by postavička něco začala dělat tak teprve pak odesílala informace?

Za další je taky možny,že posíláš ty data nějak extrémně moc velký třeba větší než je vlastně potřeba (tím myslím jestli neposílas třeba 500kB nebo tak) i to je docela pak zátěž. Lepší by bylo si vytvořit nějaký kodování který by tvuj server rozlišoval a podle toho dělal to co by měl. Dám příklad. Třeba budeš chtít poslat z clienta attack na jinýho hráče? Jak bys to nejlíp poslal? asi něco jako ID packetu a ID hráce.

Třeba takto

byte 0x05 	The packet number.
uint Serial 	The serial of the character to attack.

Takže vlastně zápis by byl dlouhej asi 0x0005hex. A pak třeba ještě rozlišovat co posílat jaky packety jen do clienta a jaky packety na server. Třeba udaje o postavičce jak jsi psal že posílas všechny jeji vlastnosti mě příjde trošku nepraktický. Nestačilo by udaje o postavičce posílat jen tehdy když se na ní něco změní? Tim nemyslím chuze ale třeba vlastnost. A ten server by to u sebe držel a posilal dal aniž by to vlastně bylo nějak nutný. Pak třeba packety na pohyb. a ty bys vlastně posílal jen souřadnice (zadny vlastnosti) a server by to zpracovaval těch par b a pak posilal jako i s vlastnostma co by u sebe držel. A ty vlastnosti by se updatovali třeba dalšími packety, tudíž by jsi neměl zátěž na posílaní ani přijmání.

Beru to podle hry Ultima Online. Packety apod jsou zde http://kec.cz/…com/uo/info/ A každá akce má svoje vlastní packety takže bych to asi tak řešil.

pokud to tak máš tak promin, nevěděl jsem. Jen sem chtěl pomoct.

Nahlásit jako SPAM
IP: 89.190.90.–
Eflyax0
Duch
7. 11. 2012   #3
-
0
-

#2 Mutagen
Zajímavé, díky. Určitě nad tím popřemýšlím. Jestli to je ale zpomalené kvůli tomu, že jsou to moc dat, to nevím... Ten update má méně než 56 bajtů. Zde je například jedna zpráva:

pozice;Eflyax;y;fáze;směr;třída;teleportace;sektor

(parametry jsou oddělené středníkem)

Pokud toto přijme jiný klient, ví podle prvního parametru, že mi má hráči Eflyax pozici a další...

Je pravda, že by bylo lepší ty data odesílat jenom za určité události. Je hloupost odesílat neustále ostatním, že jsem třeba válečník - to se asi měnit tak často nebude. To určitě předělám.

Děkuji

Nahlásit jako SPAM
IP: 213.192.34.–
ingiraxo+15
Grafoman
7. 11. 2012   #4
-
0
-

když už jsem u toho packetu, tak např. Diablo3 má paket takovýto (pokud nastane událost s předmětem)

|HItem:2,1815807946:679658227:-1076747258,86949066,1925559161,-791891397:-1:0:130763:4:10:9:501:501:0:0:6:1:2,2058771892:989542878::-1:0:-1:-1:-1:9:0:0:1:0:1:0:1625093455:|h[Rift Blockade]|h

taky se mi zdá odesílání 5x/s celkem moc.. sice záleží co to je zahru, ale RPG by tohle mít rozhodně neměla.. odesíláš vždy pouze hráče, nikoli prostředí, takže pokud se hráč zastaví třeba, tak se úplně vypne odesílání paketu do doby, dokud nezačně opět jevit aktivitu vůči okolí nebo jiným hráčům

fyzický utoky bych videl asi tak, že jen odešles flag o utoku.. klient to zaregistruje a zavolá animaci utoku postavy a jen odesíláš zranění a počet HP (zakladni info o postavě)

ty kouzla budou podstate ulně stejný, jen s tim rozdilem, že pokud např. vystrelis Fireball na hrace, ta se musi prepocitat trajektorie letu a az na klientsky strane (opet) se zavola animace o zasahu nebo ne

je to nutný takto minimalizovat a co nejvice aby delal klient

a btw. kolem 30ms je v pohode na RPG.. ale pokud mas lagy, tak je chyba jinde :)

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Mutagen0
Super člen
7. 11. 2012   #5
-
0
-

#3 Eflyax
Asi bych to neposílal takhle ale nějak rozumně ...

třeba na souradnice by ti stačilo ushort neboli

ushort X;

ushort Y;

sbyte Z; třeba.

a pak to poslat jako packet .GetBytes(); a mas souradnice o veliksoti max 5b

Nahlásit jako SPAM
IP: 89.190.90.–
Mutagen0
Super člen
7. 11. 2012   #6
-
0
-

#4 ingiraxo
Ano přesně tak jsem to myslel. Prostě udělat událost, a na každou akci vlastní packet přece je nesmysl aby posílal vlastnosti postavy který se skoro neměnej.

Edit : Vlastně server je jenom na spojeni mezi hráči. Tam bude lepi kdyby nic jinyho nedělal. Vlatně by bylo nejlepší kdyby se udaje který se nebudou měnit poprvý poslali na server a ten pak podle ID hrace to posílal ostatní a hráč to aspon nemusel posílat.

Nahlásit jako SPAM
IP: 89.190.90.–
mutagen
~ Anonymní uživatel
549 příspěvků
8. 11. 2012   #7
-
0
-

premeslel jsem ze by treba pohyb vypadal takhle
byte packetid
uint playrid
ushort x
ushort y
sbyte z
byte direction

a vlastne aby to a serveru poslalo udsje klient by spustil podle prijatyho packetu animaci na objekt a tou animaci by to posunulo na ty douradnice s tim smerem max velikost packetu by byla 10bitu. O tomhle neco vim protoze pro tu ultimu pisu scripty a dela mi to pak tam automaticky jako bot

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 80.239.243.–
Ovrscout
~ Anonymní uživatel
113 příspěvků
8. 11. 2012   #8
-
0
-

#1 Eflyax
Kromně aktuální pozice by se (podle mne) mněl posílat i směr a rychlost pohybu. Pro kouzla třeba čas začátku kouzlení(+kolik času už je odkouzleno) atp. . Takto by se nemusela data posílat tak často ale hlavně při začátku/změně/ukončení akce. Nicméně jen změny bych neposílal, občas by to chtělo plnější stav, aby se to někde nerozsypalo, to pak vypadá hrozně když každý vidí něco jiného.

U různých her je to i vidět . Když se špatně přeruší spojení tak vidíte jak váš kamarád běží a běží a běží až doběhne ke zdi a vypadá že se chce prohrabat zkrz , nebo třeba běží do kopečka a pak pokračuje dál a dál do vzduchu :)

Záleží také na protokolu, TCP zaručuje doručení(nebo hlásí chybu) ale zase se to v něm při delších výpadcích štosuje a navazování spojení chvilku trvá. UDP má výhodu že se ztracené pakety nikde nehromadí takže příchozí paket je relativně čerstvý, zase ale není zaručeno pořadí paketů a ztráta se musí vyhodnocovat ručně. Zajímalo by mne jakou variantu jste se rozhodli zvolit :)

Jinak pingy kolem 32ms jsou ještě docela pěkné :) , já mívám třeba 40-60ms a ještě se to u některých her dá snést.
 

Nahlásit jako SPAM
IP: 78.80.163.–
Eflyax0
Duch
8. 11. 2012   #9
-
0
-

Já používám TCP, port 8888. Ten engine už jsem předělal. Posílám ještě menší data, než předtím a to jen ta potřebná (při dané události). 

Nastal mi teď akorát problém při odesílání hráčů ze serveru klientovi, který se do hry přidal. Ze začátku jsem tam měl cykl foreach, který mi projel celý seznam a poslal mu to - bohužel cykl je moc rychlý a data se neodešlou (klient to takhle rychle nepobere). Vyřešil jsem to tak, že se pošlou všichni v jednom řetězci, oddělení jiným oddělovačem než jejich vlastnosti. Klient si to pak rozseká na hráče - a jednotlivé hráče na jejich vlastnosti. Pak už se jenom updatují pokud se pohnou, atd.. To už je v pořádku.

Akorát tenhle způsob asi nebude moc efektivně fungovat,  až budu ze serveru posílat klientům mapy (tímto způsobem). Narvat do jednoho řetězce všechny objekty asi nebude dobré. Zatím se mi objekty načítají u klienta ale později to budu chtít mít na serveru.

Nešla by dát do cyklu nějaká pauza (v milisekundách)? 

Nahlásit jako SPAM
IP: 213.192.34.–
ingiraxo+15
Grafoman
8. 11. 2012   #10
-
0
-

#9 Eflyax
myslim že tcp stream má vlastnosti něco jako Write/ReadTimeout

ale nechápu jaký mapy, však tohle všechno musí obsahovat klient a ty mu jen pošleš ttřeba název mapy (spíše ID), kterou má načíst

co nejvíc věcí musí dělat klient, server pouze posílá příkazy

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mixxy
~ Anonymní uživatel
179 příspěvků
9. 11. 2012   #11
-
0
-

Nepouzivej tcp,ale multicastove vysilani,usetri to rychlost serveru. Obecne je mjlticast pouzivany pro hrani a nemely by vznikat takovy lagy.

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 85.132.138.–
metthal
~ Anonymní uživatel
27 příspěvků
9. 11. 2012   #12
-
0
-

ingiraxo: to nie je packet s itemom, to je len obycajny format linkovania itemov do chatu v Diablu.

Nahlásit jako SPAM
IP: 2001:67c:1220:c1a2:ad83:3...–
ingiraxo+15
Grafoman
9. 11. 2012   #13
-
0
-

#12 metthal
to vim že to je do chatu, ale aby to ostatní uživatelé viděli, tak tohle musíš i odeslat ve formě paketu... ID itemu pravděpodobně neexistuje, když jsou generovaný hodnoty, takže jiná možnost pravděpodobne neni, než tohle poslat na server a rozeslat ostatnim

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Eflyax0
Duch
9. 11. 2012   #14
-
0
-

#10 ingiraxo
To chápu - mapy by mohli být u klienta. Není problém mapu uložit do txt souboru a znovu ji načíst. Co když si ale hráč tento txt souboru upraví? To je problém... Mapy bych chtěl mít hlavně často aktualizované, takže to musí být přes server. Možná bych mohl vytvořit nějaké speciální soubory, které nejdou otevřít v textovém editoru, ale to nevím jak se dělá. Např.: svet1.map

Nevíte to někdo?

Nahlásit jako SPAM
IP: 213.192.34.–
ingiraxo+15
Grafoman
9. 11. 2012   #15
-
+1
-
Zajímavé

#14 Eflyax
pokud nad tim takto budeš uvažovat, tak to tim pádem jde u každý hry... sice nevim jak to ošetřujou (pokud vubec), ale jedna možnost je odesílat checksum souboru (mapy) kvůli validaci (případně velikost souboru)

měl by si nějak zajistit, aby mapa nešla editovat, třeba aby byla binarně a ještě pod nějakým hashem.. nebo neumožnovat hracum vytvaret mapy, takže vše uložíš do resources.. možností je plno

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 79 hostů

Podobná vlákna

XNA - hra - střílení — založil Tomik

Hra XNA/C# Skuseny odbornik — založil Jimi

Xna jak na Input — založil Belze

Jak se naučit xna — založil James Extreme

Jak to funguje — založil RA3SK

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý