Come gestire computer più veloci in un videogioco client / server in tempo reale


15

Sto creando il mio primo gioco online usando socket.io e mi piacerebbe che fosse un gioco multiplayer in tempo reale come agar.io o diep.io.

Ma mi sono imbattuto nel problema di cercare di capire come far funzionare tutti i computer alla stessa velocità.

Ho tre idee per i modelli, ma nessuno di loro sembra giusto, e mi chiedo come lo facciano i normali videogiochi. (Puoi saltare a leggere le mie idee; ti danno solo un modo per vedere i problemi che sto avendo.)

  1. Il server consente ai client di funzionare autonomamente e passare gli aggiornamenti al server, che li trasmette poi al resto dei client. Ciò ha il problema che alcuni computer funzionano più velocemente di altri, consentendo loro di aggiornarsi più velocemente e di spostarsi più velocemente sullo schermo.

  2. Chiedi al server di dire ai client quando eseguire l'aggiornamento. Posso quindi attendere fino a quando l'ultimo client risponde (una terribile idea nel caso in cui una persona abbia un computer lento), attendere fino a quando il primo client risponde (di nuovo, in attesa di comunicazione prima di ogni frame), o semplicemente inviarlo il più velocemente possibile (che sembra avere lo stesso problema del numero 1).

  3. All'inizio del gioco, chiedi al server di comunicare ai client la velocità di aggiornamento. Ciò significherebbe che il cliente sarebbe responsabile di limitare i movimenti tra quel periodo di tempo. Ad esempio, se qualcuno riuscisse in qualche modo a premere due volte un pulsante in quel periodo di tempo, invierebbe un solo evento di pressione del pulsante. Ciò ha il problema che alcune azioni verrebbero ignorate (come la pressione del doppio pulsante) e che l'interazione si baserebbe sull'orologio del client, che potrebbe non corrispondere all'orologio del server. Il server dovrebbe quindi tenere traccia di ciascun client e assicurarsi che i relativi aggiornamenti vengano inviati all'ora corretta.

Ho fatto alcune ricerche , ma gli articoli che leggo non sembrano indirizzare specificamente cosa fare se un client invia aggiornamenti più velocemente degli altri client.

Nel mio caso particolare, ho a che fare con persone che hanno una maggiore velocità della tastiera (il loro computer invierebbe più aggiornamenti della tastiera rispetto ad altri computer).

In che modo i programmatori di solito si occupano di questo?


1
Nella mia esperienza, non lo fanno. Questo è il motivo per cui esistono macchine da gioco; quelli che pagano 5 mila dollari per un lanciafiamme all'avanguardia hanno automaticamente un vantaggio rispetto a quelli che usano ancora un Commodore 64.
Robert Harvey,

1
Quindi il mio gioco sembrerà lento perché dobbiamo giocare con il minimo comune denominatore? Sembra che il server di gioco dovrebbe impostare il tempo e spetta ai client tenere il passo o dovrai solo ritardare.
JeffO,

3
Potrei fraintendere la domanda, ma probabilmente è quello che stai cercando di utilizzare un modello client e server basato su tick. gamedev.stackexchange.com/questions/81608/… Fondamentalmente devi solo elaborare input e logica ogni X tempo (di solito 1 / N secondi, come 1/60 per la logica a 60Hz)
Christopher Wirt,

4
Dopo aver letto la domanda un po 'più da vicino, sembra che tu sia troppo concentrato sugli aspetti client del gioco. Se vuoi un gioco multiplayer "equo", il tuo server dovrà essere autorevole. Ciò significa che tutto ciò che accade ai client viene verificato o eseguito dal server. Quindi limitate le cose da qui, probabilmente attraverso un sistema basato su tick come sopra.
Christopher Wirt,

1
Ah, netcode in tempo reale. Il luogo più profondo e oscuro dello sviluppo del gioco. Benvenuto sulla nave, amico!
T. Sar - Ripristina Monica il

Risposte:


8

La tua terza idea sembra essere la più vicina a quella che penso sia la soluzione del settore per questo tipo di problema.

Quello che stai descrivendo viene comunemente chiamato tick . In ogni segno di spunta, un numero fisso di azioni verrebbe elaborato per ogni client in serie. Spesso i server di gioco avranno alcune azioni parallele quando sono in grado, ma questo è un problema molto più complicato.

È probabile che un segno di spunta abbia la forma di 1 / N secondi, con N il numero di tick al secondo o Frequenza di tick. Questo tickrate potrebbe essere molto spesso o molto raro, a seconda del caso d'uso. Il mio suggerimento personale sarebbe quello di evitare una frequenza superiore a 60 tick / secondo a meno che non si sia sicuri di aver bisogno di più. Probabilmente no :)

Le azioni dovrebbero essere atomiche. Ad esempio, in slither.io, un'azione come muoversi non dovrebbe immediatamente elaborare qualcosa come spezzare la catena, a meno che il giocatore colpito non abbia già preso la sua mossa. Questo può sembrare banale per qualcosa a livello di pixel, ma se hai a che fare con movimenti basati su piastrelle, diventa molto più ovvio e garantisce l'equità. Se il giocatore A si sposta sulla tessera X, Y e il giocatore B si trova attualmente su quella tessera, devi assicurarti che entro la fine del segno di spunta, il giocatore B rimarrà su quella tessera per qualsiasi azione tra di loro.

Inoltre, direi di evitare di eseguire i tuoi calcoli sul lato client a meno che non vengano eseguiti in modo indipendente sul lato server. Questo diventa complicato e costoso con la fisica (molti giochi optano per un tasso di tick inferiore per la fisica rispetto a molte altre azioni ed eventi a causa di ciò)

Per riferimento, ecco un buon link per integrare la tua comprensione dei server di gioco e delle reti multiplayer.

Infine, direi di non lasciare che l'imparzialità rovini il tuo server. Se ci sono exploit che rendono ingiusto il tuo gioco, correggili. Se si tratta di un computer migliore con un leggero vantaggio, direi che potrebbe non essere un grosso problema.


3
@ProQ vale la pena notare che scrivere un buon netcode non è banale! Se la tua app non funziona bene dall'inizio e il tuo netcode sembra fare schifo, non mollare. Anche le persone che lo fanno per vivere ogni giorno hanno problemi con esso. è solo che duri!
T. Sar - Ripristina Monica il

0

Il seguente sistema si assicura che tutti i client e il server condividano quasi lo stesso stato di gioco in qualsiasi momento.

Avere lo stato del gioco sia su client che su server.

Quando un client tenta di utilizzare un comando (mouse, tastiera, ecc. Altro input), osserva il suo stato del gioco se è valido.

In tal caso, inviare il comando al server, senza eseguirlo sul client di invio.

Quando il server riceve il comando, controlla il suo stato del gioco se è valido.

In tal caso, rispedire il comando a TUTTI i client con la data futura esatta dopo ciò che dovrebbe essere eseguito sul server, quindi eseguire le azioni richieste dal comando dopo un ritardo pari al tempo minimo per inviare il comando ai client . quindi registra la data, questo aiuta a fare previsioni future. Se il tempo varia troppo, rendi il tuo sistema di gioco più deterministico.

Quando un client riceve un comando dal server, osserva il suo stato del gioco se è valido, esegui immediatamente le azioni richieste dal comando, quindi osserva la data corrente e confrontala con la previsione della data ricevuta. Se non è valido, il client non è sincronizzato. (Tutti i client con una connessione simile ricevono contemporaneamente)

Se la data è precedente, hai riscontrato un problema nel passaggio precedente, risolvilo. Se la data è leggermente successiva, non fare nulla, Se la data è molto lunga, il client non è sincronizzato, vale a dire che il client è troppo indietro.

Quando un client non è sincronizzato, richiedere una copia dell'intero stato di gioco del server e utilizzarlo. Se ciò accade troppo spesso, correggilo perché è più costoso dell'invio di comandi.

Sui client, eseguire il rendering delle cose sullo schermo SOLO quando non c'è altro da fare. In scenari semplici, la funzione di rendering prende come input solo lo stato di gioco corrente.

Inoltre, puoi ottimizzare molto, usando sistemi predittivi, raggruppando i comandi, render solo le differenze ecc ...

La convalida dovrebbe differire, ad esempio, spetta al server limitare le richieste di comando / unità di tempo.


0

Non so se questo è un problema di librerie o di ambienti che stai utilizzando, ma penso che ti stia avvicinando in modo totalmente sbagliato.

Nella stragrande maggioranza dei giochi multiplayer, è solo il server che esegue calcoli reali. I client sono solo macchine IO stupide in cui solo un vero problema di prestazioni è il disegno di grafica 3D. E in questo caso non importa se il client può funzionare a 20 o 200 FPS, perché ciò influisce solo sulla grafica. Ciò significa che "aggiornamento client" non ha assolutamente alcun significato. Il cliente potrebbe provare a "prevedere" quale server potrebbe calcolare, ma ciò serve solo a smussare la sensazione di gameplay e non ha alcun impatto reale sul gameplay stesso.

velocità della tastiera più elevate

Non so nemmeno cosa significhi. La maggior parte delle persone non riesce nemmeno a tenere il passo con la velocità delle tastiere di fascia bassa, quindi come potrebbe influire sulle prestazioni dei giocatori?

Altrimenti, la domanda sembra troppo ampia e dovresti invece concentrarti su un singolo problema reale, invece di cercare di inventare un problema "generale" che potresti non avere.


una maggiore velocità della tastiera non riguarda la digitazione, ma il numero di comandi che possono essere inviati se si tiene premuto il tasto "sposta avanti" o il tasto "spara".
gbjbaanb,

@gbjbaanb E come è un problema? Dovresti preoccuparti solo dei comandi premuti e rilasciati. Non dovresti preoccuparti di quanto velocemente lo aggiorni.
Euforico,

Ti importa se stavi gestendo tutti gli eventi come l'OP previsto - sul client Quindi se premendo w ti facessi avanzare di un po 'di distanza e la tua tastiera fosse più veloce di quella di qualcun altro, andresti più veloce di loro. L'ultima cosa che vuoi è fare un gioco di corse che devi tenere premuto un tasto per andare avanti!
gbjbaanb,

@gbjbaanb No. È sbagliato. Il server sa che "il giocatore sta andando avanti" e quindi ogni 1/60 di secondo aggiorna le posizioni di TUTTI i giocatori in base a se stanno andando avanti. Ecco come funzionano TUTTI i giochi. Il ciclo di aggiornamento è lo stesso per tutte le entità in gioco e gli aggiornamenti NON SONO basati su eventi dell'interfaccia utente.
Euforico,

1
No, non è questa la comprensione dell'OP, il motivo per cui l'ha chiesto e il motivo per cui hai detto "Non so nemmeno cosa significhi". Se capisci la posizione dei PO, allora la sua domanda ha senso. Se l'OP ha codificato il suo gioco in modo che funzioni con un loop di gioco basato interamente sulla velocità con cui gli eventi vengono consegnati dal client, questo è ciò di cui si sta chiedendo: ti sbagli ad applicare un design ipotetico del gioco a ciò che l'OP sta effettivamente chiedendo, indipendentemente dal fatto che il suo design sia sbagliato per la maggior parte degli standard.
gbjbaanb,
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.