"Noi incoraggiamo gli individui, consapevolmente curiosi, a passare dalla complessità alla semplicità, dall'interno all'esterno e, a metà strada fra la ricerca e la negazione del significato, vogliamo che i curiosi facciano una dannata scelta". Wachowski

giovedì 26 settembre 2013

NET CODE: (pt.5) LAG COMPENSATION

Quinto appuntamento con questa serie di articoli dedicati alla comprensione dei meccanismi e problemi generali dietro all'architettura di un gioco multiplayer.
Siamo finalmente giunti al momento di parlare di hit detection ovvero quella funzionalità del sistema di verificare se un oggetto che ha un potere nocivo colpisca o meno un oggetto che ha un parametro di salute.
Ovviamente se non avete seguito (e spero compreso, con tutti i miei limiti espositivi) gli articoli precedenti, non andate avanti, altrimenti vi risulterà ostico capire che cosa si intende per passato, presente e futuro.  Meglio partire dal primo articolo.
Prima di tutto, fughiamo un dubbio.

Hit detection non è collition detection.

La collition detection rappresenta
il fatto che due oggetti si tocchino. Quando andate addosso ad un muro, di sicuro non gli passate dentro. A questo pensa appunto la collition detection. A bloccarvi davanti al muro anche se state muovendo il giocatore.
Quando invece vi arriva una granata, ad esempio, la hit detection determina chi viene investito dalla deflagrazione, assegnando un valore da sottrarre alla salute del giocatore in funzione della distanza o in funzione di una qualsiasi scelta degli sviluppatori.
In sostanza, la hit detection è certamente una collition detection,  ma con effetti ulteriori.

Se guardate un po’ in giro nell’internet, troverete buffe discussioni su accanimenti se la hit detection sia fatta dal client o dal server.

Se è fatta dal client, questo vuol dire che il client invia pacchetti al server del tipo “ho controllato che il proiettile arriva in testa al giocatore avversario, perciò sottrai, a lui, questa quantità di vita oppure notificagli che è morto.

Se è fatta dal server, invece, il client manda solo l’informazione della posizione e direzione di un proiettile e la hit detection viene demandata dal server.
Bastano solo un paio di neuroni attivati nel nostro cervello per dire “e chissenefrega!”.
L’informazione che contiene la nostra morte ci proviene sempre dal server, sempre con ritardo pari al nostro lag, perciò forse non ci interessa sapere chi lo fa.

Purtroppo ne dobbiamo accendere almeno altri due di neuroni per capire come mai interessi così tanto e fare le seguenti valutazioni:

1) Se la hit detection è fatta nel client, basta un qualsiasi programmino per hackerare il client e inviare pacchetti al server che uccidano tutti quelli presenti nella mappa. Molti burloni, come quello mostrato nel video qui fanno proprio questa cosa.
Alcuni di questi programmi sono cos' ben realizzati da permettere uccisioni, ad esempio, con la cassetta di munizioni.
Se tirate una cassetta ad un avversario noterete che gli passa attraverso, perciò il client deve essere perciò stato manomesso in una maniera addirittura digeribile dal server.


2) La hit detection nel client ci permette di uccidere qualcuno nel nostro presente in maniera molto più affidabile che spostandola nel server.
Analizziamo questa affermazione che sembra abbastanza contradditoria.

Vi ricordate tutte le discussioni precedenti sul fatto che il vostro presente è il futuro del sistema e che i nemici, sul vostro schermo, sono fantasmi spostati nel futuro di una quantità pari al vostro lag?

In questo modo, il sistema ha faticato e bestemmiato in 7 lingue per fare in modo che ciò che voi miriate sia “affidabile” per voi. Il sistema ha lavorato per trasportarvi tutto nel vostro presente. Riuscendoci o non riuscendoci non importa. Ha dato il massimo.

Per quale motivo mai dovrebbe farlo lato server?

Nella realtà si può fare lato server utilizzando un meccanismo che si chiama lag compensation.

Per capirlo spostiamo la nostra asse tempi sul server e ipotizziamo il caso nel quale un giocatore stia sparando ad un altro che corre.

Nel presente del server, si ricevono i pacchetti dei giocatori: uno ha un proiettile e la posizione del giocatore, mentre l’altro ha solo una posizione.
Nel presente del server, questi pacchetti corrispondono al passato dei giocatori, un passato purtroppo non uguale visto che ciascuno potrebbe avere un lag differente.
Come fare allora?

Semplice. Poiché il server può memorizzare le posizioni di tutti, può compensare il lag della vittima rispetto all’istante nel quale ha ricevuto il proiettile.

Se la vittima lagga 1 secondo e il carnefice ne lagga 4, il server prende come riferimento il proiettile del carnefice e ricostruisce la posizione che aveva la vittima 3 secondi prima. Una cosa in teoria semplice visto che si tratta di andare a ravanare nelle informazioni che un server può salvare.
Occhio che non si compensa il lag con i proiettili, ma solo con le posizioni dei giocatori. I proiettili vengono valutati appena arrivano.

Nessuna predizione. Nessuna monetina tirata in aria. L’informazione verrà ricostruita su basi certe.
Peccato che però la ricostruzione sarà vittima di quello che in ingegneria si chiama teoria del campionamento e più in generale del teorema di Nyquist.
Fatemi fare il Piero Angela della situazione e fate un ultimo sforzo.
Immaginate di ridisegnare la posizione di una palla che rimbalza continuamente, per 5 volte al secondo, ad un’altezza di un metro, fotografando la palla solo 2 volte al secondo.

Non ci vuole un genio per capire che, prendendo solo due foto in un secondo, potremmo non vedere mai la palla sbattere per terra o arrivare alla massima altezza.
La ricostruzione che avremmo sarebbe un insieme di foto ( e quindi posizioni) che tutto assomiglia che ad un moto elastico.
Nyquist dice che non potete ricostruire un segnale (il rimbalzo di una palla) che ha una frequenza (5 volte al secondo) campionandola (fotografandola) con frequenza minore del doppio della frequenza del segnale (ovvero facendo meno di 10 foto al secondo).

Con 2 foto al secondo, verrà una ciofeca.
In effetti il server è vittima della stessa cosa.
Riceve tanti pacchetti separati nel tempo come fossero tante foto, nella speranza di ricostruire e validare il segnale (la corsa del giocatore).

Metteci lag (ritardo), jitter (variazione nella frequenza di ricezione dei pacchetti) e perdite di pacchetti ed ecco che forse adesso avrete un po’ meno scuse per prenderla con battlefield.
Ovviamente la lag compensation, con una hit detection lato client, è utilizzata solo per verificare e confermare una kill e non come calcolo intero.

Anche lì ovviamente una ricostruzione può fallire e la vedremo nel prossimo articolo.
Continuiamo perciò, nel prossimo post, a vedere che cosa sia client o server side in battlefield, partendo da una spifferata di uno sviluppatore.

E finalmente vedremo un video su come un server, pur facendo hit detection, non sia in grado di compensare la presenza del lag.

Adesso qualcuno inizia a rendersi conto della difficoltà ingegneristica di progettare un net code con reti internet lente come le nostre?

2 commenti:

  1. Da buon Tecnico Informatico di Reti mi sono sempre reso conto di queste problematiche.
    Ma messe così con "calcoli" molto concreti ci si rende conto che c'è già da ringraziare l'onnipotente di quello che abbiamo.
    Forse il problema è più il fatto che esiste una CLASSIFICA e tutti umanamente siamo incentivati a "vincere" e quindi ogni minimo "lag", "errore" ci infastidisce.
    Forse il problema è prendere troppo sul serio quello che alla fine è una passione/gioco.
    Forse il problema è più sul lato umano che sul lato tecnico del gioco.

    Più leggo e più amo questo tuo blog.
    Grazie mille per il tempo che investi in gioco, ricerca, esempi chiari e a scrivere queste pagine che dovrebbero leggere tutti. Tutti. Prima di approcciarsi al mondo di BF.
    Sicuramente se tutti leggessero e applicassero quello che sta scritto in queste pagine BF sarebbe vissuto in maniera migliore da tutti per tutti.

    OTTIMO lavoro.

    RispondiElimina
  2. Si muore dietro i muri, fin qui nulla di nuovo,
    ma ho avuto l'impressione di essere colpito da avversari che devono ancora girare l'angolo (tipo il "vecchio" prefire),
    mi spiego meglio
    mentre corro lungo un muro avvicinandomi ad un angolo ed il mio avversario penso stia facendo lo stesso dall'altra parte, quando arrivo in prossimita dell'angolo vengo colpito prima di vederlo spuntare.
    un po' come quando muori 1 secondo dopo esserti riparato ma al contrario.
    la domanda è: devo smettere di bere o succede anche a te?
    ti prego illuminami
    grazie :)

    RispondiElimina