Sto facendo un gioco con Unity e sto riscontrando problemi nel tentativo di sincronizzare la rete. La simulazione deterministica è impossibile perché la logica interna di Unity è basata sul float. Sto cercando di creare una soluzione che funzioni su un autorevole modello client-server, in cui la posizione di ogni soldato è corretta dal server 5-10 volte al secondo. Ciò si ottiene inviando datagrammi UDP e verranno implementate misure per garantire la consegna. Tra correzioni il client simula il gioco nel miglior modo possibile.
I soldati non si muovono spesso in linea retta. Si impegnano nel floccaggio e incontreranno molti ostacoli che devono percorrere. I soldati esistono come individui e non esistono come parte di un oggetto squadra.
Ci sono cose che possono essere fatte per ridurre il consumo di larghezza di banda che non sono l'attenzione qui, perché sono al massimo miglioramenti temporanei. Come solo inviare le posizioni dei soldati che si spostano e / o osservano e comprimono i dati prima della trasmissione.
Il problema è semplice. Se ho dieci soldati che corrono, va bene, ma se ne avrò un migliaio allora l'uso della larghezza di banda diventa irragionevole. Per lo meno abbiamo bisogno di inviare un soldato id (ushort) e posizionare (float, float, float) per soldato. Al momento questo è 2 + 4 + 4 + 4 = 14 byte . Potrebbero essere necessari più dati, ad esempio la direzione di orientamento (i soldati non guardano mai in alto o in basso).
14 * 10 * 1000 = 140kb / s ... troppo!
La domanda è questa:
Come possiamo ridurre il numero di byte inviati per soldato al minimo assoluto e avere ancora un risultato sincronizzato?
POSSIBLE SOLUTIONS:
1. Un'idea che avevo era che, poiché la velocità massima di un soldato non cambia, questo ci permette di correggere la posizione di ogni soldato con un valore assoluto relativo all'ultima posizione nota. Ma anche questo potrebbe risentirne.
Invece di inviare un float per l'asse XYZ della posizione, inviamo un sbyte. Poiché questo è compreso tra -128 e 127, possiamo leggerlo / scriverlo per dire che la nuova posizione è una percentuale della velocità massima del soldato dall'ultima posizione. Se funzionasse, ridurre i dati inviati da 14 byte a 5. Ma anche il 36% è ancora 50kb / s per 1000 soldati.
Potenzialmente ciò potrebbe essere ridotto a 4 byte alcune volte, poiché i soldati non sempre si muovono su o giù (asse Y). Ma questo è, come ignorare i soldati che non si muovono, non il problema.
2. Un'altra idea che ho avuto è stata quella di ridurre l'asse XYZ a 12 bit (1,5 byte). Ogni asse ha 4 bit, 3 dei quali vengono utilizzati per trovare un valore di distanza. 3 bit ci permettono di contare da 0 a 8. Ci sono sei valori tra la fine di zero o la velocità massima. Abbiamo una gamma di valori che possono essere utilizzati in quanto "abbastanza vicini". L'altro bit determina se questo è positivo o negativo. Il server forza quindi una correzione sui soldati prima che invii le loro posizioni al cliente, forzando la loro distanza dall'ultima posizione per conformarsi a uno dei valori "abbastanza vicini".
Inoltre, se non ci saranno più di mille soldati vivi in una volta sola, potremo assegnare soldati a un ID vivente, e quindi accorciare l'ID di rete da 16 bit a 10, consentendoci di contare fino a 1024.
In totale ciò ridurrebbe i dati inviati per soldato da 14 byte a 22 bit (2,75 byte). Sospetto che sarebbe meno probabile che la prima idea mantenga la sincronizzazione. Il risultato potrebbe semplicemente essere troppo nervoso. Se funzionasse sarebbe il 20% della larghezza di banda originale a 28kb / s.
...
Tutte le idee sono benvenute a questo punto. Mi sono concentrato sulla creazione di vector3 più piccoli e più piccoli, ma potrebbe esserci un modo molto migliore di fare ciò che fa qualcosa di completamente diverso.