Se non l'hai già fatto, ti suggerisco di leggere questi due articoli profondi ma comprensibili: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking e http://fabiensanglard.net/quake3/network.php .
Questi spiegano perché si consiglia di utilizzare l'invio di pacchetti a "intervallo fisso". Per essere brevi, in effetti è importante soprattutto per i pacchetti inviati dal server.
L'invio di un pacchetto ha un costo fisso e la dimensione massima di un pacchetto di rete è di circa 1,5 KB. Quindi se hai ad esempio 16 giocatori sul tuo server, ogni frame quando calcoli il movimento per un giocatore, il codice ingenuo potrebbe inviare un pacchetto di aggiornamento a ciascun giocatore dopo ogni risoluzione di movimento, quindi 16 * 16 = 256 pacchetti. Se hai un framerate di 30, sono 7680 pacchetti.
Un approccio migliore è quello di creare un buffer in ogni inizio del frame, concatenare in esso il tuo aggiornamento di 16 posizioni calcolate e quindi inviarlo ai tuoi 16 giocatori.
Ora si inviano solo 480 pacchetti al secondo per gli stessi risultati.
Nel caso da giocatore a server, ciò significa solo che dovresti inviare, nello stesso pacchetto, un massimo di dati, come; sembrava posizione, le azioni hanno chiamato questo frame e così via.
Circa la seconda parte della tua domanda - il modo in cui ho scelto di ridurre la sensazione di ritardo è stato quello di inviare queste informazioni al server su ciascun frame:
posizione attuale attuale del giocatore (utilizzata dal server per verificare se le posizioni lato server e lato giocatore non sono troppo desincronizzate).
Posizione stimata del giocatore in 1 secondo: calcolata dal cliente: se il giocatore non cambia la direzione del mouse e lascia la tastiera nello stato corrente per 1 secondo, dove sarà il giocatore? (non ci importa delle collisioni) Se il giocatore non si muove, la sua posizione stimata in 1 secondo è la sua posizione attuale.
La posizione che osserva.
Ogni volta che il server riceve queste informazioni aggiorna la posizione futura e la posizione osservata e l'entità giocatore alla fine si sposta verso la sua posizione futura.
I giocatori non sono mai esattamente sincronizzati, ma la risposta in ingresso è istantanea (la cosa più importante per me) e ho trovato le posizioni previste sufficientemente accurate per me.