Come posso assegnare gli ID entità in modo affidabile in un gioco di rete?


17

Sto lavorando su un sistema di entità per un gioco in rete e sto assegnando a ciascuna entità un ID intero a 32 bit univoco che posso usare per serializzare i riferimenti alle entità e alle entità stesse.

Attualmente sto solo incrementando un contatore ogni volta che viene creata un'entità. Suppongo che gli ID finiranno per esaurirsi, ma non mi aspetto davvero di avere 4 miliardi di entità. Inoltre, questo evita il problema se l'entità n. 5 viene distrutta e otteniamo un ID di 5. È inteso fare riferimento al nuovo n. 5 o al vecchio n. 5 eliminato?

Il problema è che non sono sicuro di come gestire / evitare le collisioni. Attualmente, se un client riceve un aggiornamento per un'entità con un ID superiore al suo attuale "ID libero", supera semplicemente il suo ID libero fino a quello passato. Ma questo non sembra molto robusto.

Ho pensato forse di assegnare intervalli a ciascun client in modo che possano allocare entità senza conflitti (diciamo che i primi n bit sono il numero del giocatore) ma sono preoccupato di cosa succede se gli intervalli hanno iniziato a sovrapporsi nel tempo.

C'è un modo migliore di gestirlo? Dovrei anche preoccuparmi degli ID che traboccano o superano la fine dell'intervallo consentito? Potrei aggiungere codice per rilevare questi casi, ma cosa farebbe se accadessero oltre all'arresto anomalo.

Un'altra opzione è quella di utilizzare qualcosa con una maggiore possibilità di essere unico come un GUID a 128 bit, ma sembra davvero pesante per un gioco che sta cercando di ridurre al minimo il traffico di rete. Inoltre, realisticamente non avrei mai avuto bisogno di più entità contemporaneamente, quindi mi sarei inserito in un numero intero a 32 bit o addirittura a 24 bit.

Grazie!


1
Perché non tutti i clienti hanno le stesse entità? I client non sono sincronizzati? O è un grande mondo di qualche tipo in cui i clienti non eseguono tutti lo stesso gioco.
Filippo,

2
Finora la mia architettura segue vagamente quella di UE3 (maggiori informazioni qui ). Fondamentalmente i clienti conoscono solo le entità che sono vicine a loro nel mondo. Inoltre, i client non vengono eseguiti in modalità di blocco, ma il server controlla la maggior parte della logica e può sovrascrivere i dati del client in qualsiasi momento. Immagino ora che ci penso, potrei solo consentire al server di creare entità e fare in modo che i client utilizzino RPC per farlo. Non sono sicuro dell'approccio migliore. Sono un programmatore grafico di giorno :)
Lucas il

1
Penso che, come dici tu, dovrebbe essere gestito solo dal server se ciò è fattibile all'interno della tua architettura. Quindi mantieni una pila di ID entità liberi che esiste separatamente dall'elenco / mappa entità, in modo da sapere quali ID sono disponibili. In mancanza di un modello server autorevole, l'approccio a distanza dovrebbe funzionare correttamente, in termini di intervalli. Quattro miliardi sono molti, anche per dividere tra 4000 giocatori in un MMO. Quindi utilizzare lo stesso approccio per tenere traccia degli ID disponibili come con un'autorizzazione. server.
Ingegnere,

@Lucas, il tuo link dice "Il server identifica il set di attori" rilevanti "per ogni client". Ciò implica che il server sia a conoscenza di tutte le entità ed è in grado di elencarle.
Kylotan,

1
Certo, ma se un client crea una nuova entità A ma prima che possa ricevere il messaggio di creazione il server crea una nuova entità B, a entrambi viene assegnato lo stesso ID "libero".
Lucas

Risposte:


13

Quello che ho fatto è fare in modo che il server faccia tutto . I client possono semplicemente chiedere al server di fare qualcosa, ma non possono fare nulla da soli. In questo caso, il server sarà sempre quello che assegna gli ID e il problema risolto.

Non ho affrontato la previsione sul lato client mentre aspettavo che il server approvasse azioni come: "Spara un razzo" o "Crea una stazione solare qui". Queste azioni vorranno creare entità e le entità hanno ID. Finora, sono solo seduto sul mio pollice in attesa del server, ma credo che ciò che deve essere fatto sia creare un'entità temporanea mentre aspetti l'approvazione del server. Quando si riceve l'approvazione del server, il server assegnerà un ID e sarà possibile aggiornare o sovrascrivere l'oggetto temporaneo.

Inoltre non ho avuto a che fare con un overflow di ID, ma se il server ha il pieno controllo e rileva un overflow, potrebbe fare tutto ciò che ritieni necessario (riavvia a 0, scegli da uno stack libero, crash, ecc.) E tutto i clienti non lo sapranno nemmeno o si preoccuperanno. I client accetteranno semplicemente gli ID forniti dal server.


Grazie per tutte le informazioni utili ragazzi! Ho finito per andare con il server crea tutte le entità approccio, ma se trovo che introduce troppa latenza proverò il metodo di Trevor.
Lucas,

Per ID specifici del client (necessari per la previsione durante l'attesa del server) è possibile semplicemente utilizzare un prefisso sull'ID.
danijar,

6

Quando l'ho fatto per una partita multiplayer commerciale, ho fatto esattamente quello che mi proponi: usa un numero intero GUID a 32 bit, dove gli otto bit principali sono il numero del giocatore e i ventiquattro bit inferiori contengono un numero univoco locale.

Se / quando il numero locale trabocca (nel mio caso, non accadrebbe quasi mai; in condizioni di utilizzo normale, ci sarebbero voluti dai quattro ai cinque giorni di riproduzione continua in una singola sessione di rete per farlo accadere), il proprietario avrebbe inviato un Messaggio "Ripristino di tutti i miei oggetti" e rinumerare tutti gli oggetti ancora esistenti a partire da zero fa. Il messaggio diceva a tutti i peer di scartare gli oggetti che avevano ricevuto e di interrogarli nuovamente.

Un approccio più elaborato sarebbe un messaggio "Oggetto con GUID 'n' is ora Oggetto con GUID 'm'" per ogni oggetto esistente. Ma nel mio caso, era improbabile che accadesse davvero, e non pensavo che alla gente sarebbe dispiaciuto davvero che gli oggetti remoti sparissero dal mondo per mezzo secondo, dopo cinque giorni di gioco senza sosta in una singola sessione di rete. ;)


Questa è una buona idea per gestire l'overflow. Semplice, ma non ci ho pensato :). "Dimenticare" tutte le tue entità è bello poiché può sostanzialmente riutilizzare lo stesso codice che il client usa quando si unisce al gioco
Lucas,

4

Se i tuoi clienti possono generare le proprie entità, immagino tu abbia un gioco multiplayer peer-to-peer.

In tal caso, probabilmente non hai troppi client. Certamente non più di 256. E l'id dell'entità è garantito per adattarsi a 24 bit (16000000+ entità sono sufficienti per tutti!). Quindi, basta rendere il byte più alto del tuo ID uguale all'ID del client:

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

o qualcosa.

E se sbaglio e hai un server autorevole, non creare mai nuove entità sui client.


1

Sto usando il metodo "più ingenuo" (solo incrementare un numero intero per ogni nuovo ID) nel mio gioco multiplayer persistente e funziona bene perché non lascio che il client crei un nuovo ID: s.

Se lasci che il cliente decida (usando una sorta di tecnica GUID spiegata), il cliente può anche introdurre vari bug assegnando un vecchio ID a un nuovo oggetto (è proprio quello che ho pensato in cima alla mia testa pensando come 5 secondi , potrebbero esserci molte altre lacune).

Come al solito, per evitare imbrogli , il server dovrebbe fare TUTTA la creazione e la validazione .

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.