So che la mia configurazione multiplayer super semplice non è probabilmente una buona idea, ma perché?


11

Sto realizzando un semplice MOBA solo per divertimento. Stavo realizzando tutto per giocatore singolo, poi ho capito "oh merda, probabilmente dovrei aggiungere il multiplayer, eh."

Non ho mai fatto nulla con il networking prima, quindi imparare a integrare Lidgren nel mio gioco è stato divertente e fantastico. Il fatto è che praticamente so che il modo in cui sto facendo le cose è sbagliato, perché non è abbastanza robusto per essere utilizzato dai giochi tradizionali, per quanto ne so, ma cosa c'è che non va?

Quello che sto facendo è, fondamentalmente, ogni volta che un giocatore fa un'azione, invia un messaggio al server dicendo "hey, ho appena fatto questa cosa". Il server e il client eseguono entrambi la stessa simulazione. Il server quindi invia un messaggio a tutti gli altri client dicendo loro che quel tipo ha fatto quella cosa.

Per la maggior parte, tranne in alcuni casi, quando un giocatore fa una cosa, il cliente assume che sia bello e lo fa da solo. Quindi, quando fai clic con il pulsante destro del mouse da qualche parte per spostarti lì, il client di quel giocatore inizia a spostare lì il suo ragazzo e quindi invia un messaggio al server raccontandolo.

Quindi in poche parole:

  • Il giocatore 1 lancia un incantesimo per farlo muovere più velocemente del 100% per sei secondi
  • Il client locale del giocatore 1 aggiunge quel buff al suo oggetto Unit
  • Il client del giocatore 1 invia un messaggio al server dicendo "hey ho appena lanciato questo incantesimo"
  • Il server si assicura che avesse davvero abbastanza mana per lanciare quell'incantesimo e, in tal caso, aggiunge quel buff alla copia del server dell'oggetto Unit
  • Il server invia un messaggio a tutti gli altri client dicendo "hey questo ragazzo ha appena lanciato questo incantesimo"
  • Ogni altro client riceve il messaggio e va "ah va bene," e aggiunge quel buff all'oggetto Unità locale per quel giocatore

Ho sfogliato le cose per vedere come i grandi giochi fanno il multiplayer, ed è un po 'confuso per qualcuno che sta appena iniziando a dilettarsi in queste cose, ma sembra che il motore di Source mandi un pacchetto contenente tutte le modifiche a tutto ciò che è nel mondo ogni tick? Ancora una volta, totalmente nuovo a questa roba, ma puoi davvero spingere così tanti dati così frequentemente?

Scusate se è un po 'sconclusionato, ma in sostanza, mi chiedevo perché il mio sistema più semplice non è la strada giusta da percorrere, perché se lo fosse, altri giochi lo userebbero, giusto?


6
Un passaggio che manca è che il server invia anche questo messaggio al client originale (non solo a tutti gli altri) per confermare o negare il risultato della simulazione, quindi il client di origine continua o si adegua alla nuova realtà. A parte questo, questo metodo va bene e le altre risposte che seguono ti aiuteranno a capire meglio altri aspetti.
Patrick Hughes,

1
La cosa fantastica è che il resto di noi ha ragionevoli speranze che la rete non sia così difficile. È fattibile.
ashes999,

Risposte:


12

Oltre alla risposta di Byte56, ci sono un altro paio di cose da considerare:

Come comunicherai tra i clienti i movimenti dei giocatori? A differenza della maggior parte delle azioni degli altri giocatori, che tendono ad essere eventi isolati e probabilmente un po 'rari, il movimento è continuo. Esiste un limite alla velocità con cui è possibile (e si desidera, in tal caso) inviare e ricevere aggiornamenti. La previsione sul lato client citata da Byte56 in genere comporta aggiornamenti periodici sulla posizione e la velocità del client. Il client quindi interpola localmente tra loro, usando qualcosa come una spline cubica .

Un secondo problema, che si ricollega ai precedenti, è che UDP non ha una consegna garantita. Non puoi essere certo che ogni messaggio che invii arrivi o arrivi addirittura nel giusto ordine. È possibile inviare i pacchetti 1, 2 e 3 e il server riceve 3, quindi 1 e non 2. Spesso saranno nell'ordine giusto e spesso arriveranno, ma non sempre. Pertanto, è necessario un sistema robusto per perdere i pacchetti. È sufficiente un semplice sistema di conferma. Tipicamente utilizzato è un campo di bit che dice all'altro nodo se ha ricevuto gli ultimi 32 messaggi (per un int a 32 bit) e quale è stato l'ultimo messaggio ricevuto. In questo modo, puoi etichettare i messaggi come critici o meno e inviare nuovamente se non li ricevono. C'è una discussione abbastanza decente qui .

Inoltre, devi tenere presente che, quando lo fai, i tuoi clienti non saranno sincronizzati tra loro. Ognuno mostrerà gli altri giocatori che si interpolano tra i loro due precedenti frame di rete mentre stai lavorando al successivo, nel migliore dei casi. Quindi hai bisogno di un sistema che tenga conto (in modo equo) che ciò che un giocatore ha visto quando ha eseguito un'azione non era lo stato reale del gioco quando ha fatto quell'azione. Stava reagendo a un vecchio stato di gioco non sincronizzato.

Infine, se questo gioco vuole essere competitivo, devi anche preoccuparti di barare. Pertanto, per quanto possibile (e ragionevole), è necessario diffidare dei clienti e verificare che le loro azioni siano possibili. "No, non puoi attraversare quel muro. No, non puoi camminare più veloce della tua velocità di corsa. No, non puoi pretendere di aver colpito quel bersaglio." eccetera.

Per ulteriori idee, ti consiglio di sfogliare gli altri articoli in quel secondo link.

In bocca al lupo!


6

Quello che stai descrivendo è essenzialmente una previsione sul lato client , ma non dici cosa succede quando il server e il client non sono d'accordo.

Si è evoluto dai giorni in cui il client era solo un terminale stupido, inviando i suoi input al server e il server ha detto al client il risultato. Tuttavia, una volta che i giochi si sono spostati oltre la LAN (e spesso prima) la latenza era evidente in questa situazione. Quello che stai descrivendo, la previsione sul lato client è stata introdotta per risolvere il problema. Ora il client simula anche il movimento mentre attende che il server risponda. Quindi giungono ad un accordo sul risultato. Con il server che è l'autorità.

I prossimi passi sono il modo in cui rispondi ai disaccordi. Se non si dispone di alcun elemento per questo, si otterrà il banding o il tele-porting del client quando il client e il server non sono d'accordo.


5

Timing. Le altre risposte non menzionano i tempi degli eventi sul server e sui diversi client. A seconda del gioco, questo potrebbe essere qualcosa a cui fare attenzione. La latenza (alias Lag) introduce un ritardo variabile tra quando viene inviato un pacchetto e quando viene ricevuto. Il tempo può essere complicato, ma cercherò di spiegare al meglio i potenziali problemi. Ci sono alcuni giochi che possono cavarsela senza preoccuparsi di questo, ma ecco un semplice esempio di dove può causare problemi.

Supponiamo che tutti agiscano sui pacchetti non appena arrivano.

@ Time 0 (wall time), Player 1 puts up a shield   (Message has been sent, but not received by anyone)
@ Time 1, Player 2 shoots player 1   (Message has been sent, but not received by anyone)

Supponiamo che Time 0 (T0) e T1 siano vicini.

Cosa succederà dopo dipende da chi lo sta guardando e dall'ordine in cui i pacchetti arrivano sul server. Il server dovrebbe sempre avere l'ultima parola. Se il server riceve i pacchetti nell'ordine sopra indicato, il server applicherà lo scudo prima dello sparo e il giocatore 1 (P1) sopravviverà. Dal punto di vista di P1, dopo aver installato lo scudo stesso, vedrà lo scudo prima del tiro e sopravviverà. Ma che dire di P2? Vedranno il colpo subito perché lo hanno sparato, ma vedranno prima lo scudo? Se (T0 + latency between P1 and the server + the latency between the server and P2) > T1lo scudo verrà fuori dopo il tiro e P2 penserà che il loro tiro abbia ucciso P1. Il server dovrà correggere questa situazione in qualche modo.

Se tuttavia, il server riceve i pacchetti nell'ordine inverso (il che è del tutto possibile, anche se T0 <T1), si verifica il contrario. P1 è sbagliato (e morto), mentre P2 è corretto (e vittorioso).

Esistono alcuni modi per affrontare situazioni come questa, ma la più semplice è lasciare che il server faccia tutto. Puoi provare a simularlo sul client, ma non consentire azioni permanenti, come la morte. I giocatori dovranno attendere importanti conferme di cambio di gioco dal server.

L'invio di un timestamp con azioni può essere utile. Se ti fidi principalmente dei clienti, puoi usare questi timestamp per determinare quale azione è avvenuta per prima, invece di seguire la nostra prima ipotesi. Questo può essere difficile, perché ricevere messaggi dal passato di solito significa che devi essere in grado di invertire il tempo.

Il tempo è divertente eh? Qualunque cosa tu faccia, è utile essere consapevoli di questi problemi di tempo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.