Le netcode déterministe expliqué : prédiction, rollback et compensation de latence
Les jeux en ligne masquent la latence avec prédiction, simulation déterministe, rollback et compensation de latence. Une analyse technique des compromis.

Sur cette page
Deux joueurs appuient sur le même bouton au même instant. Sur un canapé, le résultat est immédiat et identique. Sur internet, ces entrées doivent survivre à un aller-retour à travers routeurs, congestion et physique. La lumière dans la fibre met des dizaines de millisecondes à traverser un océan, et les chemins internet réels y ajoutent mise en file d'attente et jitter. Tout jeu compétitif en ligne est donc un exercice de tromperie : faire croire aux joueurs que leurs actions prennent effet instantanément alors que la vérité est encore en train de voyager sur le réseau.
À lire aussi: Epic Games passe à l'IA d'abord sur son jeu de tir Disney reporté · Google lance Playground, une plateforme d'IA qui transforme des prompts en jeux jouables.
Voici l'histoire des astuces derrière cette illusion (prédiction, simulation déterministe, rollback et compensation de latence), pourquoi chacune existe, ce qu'elle coûte, et pourquoi un jeu de combat, un jeu de stratégie en temps réel et un shooter résolvent le même problème de manières réellement différentes.
La contrainte : la latence est inévitable
Un jeu en réseau possède une autorité (généralement un serveur) qui décide de ce qui est réel. L'entrée d'un joueur doit atteindre cette autorité, être traitée, et l'état résultant doit revenir. Cet aller-retour est le ping, et il n'est jamais nul.
À 60 images par seconde, une image dure 16,7 millisecondes. Un ping de 100 ms parfaitement ordinaire couvre donc environ six images entre l'appui sur un bouton et la réponse du monde. Pour un jeu au tour par tour, c'est sans importance. Pour un jeu de combat, où une seule image décide si un combo touche, ou pour un shooter d'arène, où un headshot tient à quelques degrés, c'est tout le problème.
Les jeux l'attaquent dans deux directions : prédire l'avenir et corriger ensuite, ou retarder l'entrée du joueur local pour que les joueurs distants aient le temps de rattraper. Presque tout netcode réel est un mélange des deux.
Prédiction côté client et réconciliation serveur
Le modèle le plus simple (envoyer l'entrée, attendre le serveur, dessiner le résultat) semble cassé. Le Quake d'origine fonctionnait ainsi, et les joueurs en ressentaient chaque milliseconde.
La solution, popularisée par QuakeWorld et documentée par Gabriel Gambetta, consiste à laisser le client exécuter localement le même code de déplacement dès qu'une touche est pressée, tandis que le serveur reste autoritaire. Le client et le serveur n'ont besoin de s'accorder étroitement que sur le personnage du joueur lui-même, aussi le client prédit-il ce personnage immédiatement.
Quand la mise à jour du serveur arrive, elle n'écrase pas simplement le monde du client. Elle dit en substance : voici l'état autoritaire, et voici le dernier numéro de séquence d'entrée que j'ai traité. Le client jette les entrées que le serveur a déjà acquittées, se réinitialise à l'état du serveur, puis rejoue les entrées que le serveur n'a pas encore vues.
# Client, à chaque tick de simulation fixe
inputs = sample_local_input()
send_to_server(tick, inputs)
buffer[tick] = inputs
state = simulate(state, inputs) # agir maintenant, ne pas attendre
# Quand une mise à jour autoritaire arrive...
on_server_update(server_state, acked_tick):
state = server_state
for t in range(acked_tick + 1, current_tick + 1):
state = simulate(state, buffer[t]) # rejouer l'entrée non acquittée
Ce rejeu est l'essence de la réconciliation serveur. Il garde le joueur réactif et le serveur aux commandes. Les corrections sont rares (le même code de déplacement déterministe sur les mêmes entrées tombe généralement d'accord) et elles sont lissées plutôt qu'imposées d'un coup.
La prédiction côté client fonctionne mieux quand un résultat dépend surtout de l'entrée du joueur local lui-même. Elle ne peut pas prédire, par exemple, se faire tirer dessus par quelqu'un que le joueur ne voit pas; ce type d'événement arrive depuis le serveur sous forme de correction.
Déterminisme, arithmétique à virgule fixe et lockstep
Une autre famille de jeux ne prédit pas du tout. Elle n'envoie que les entrées et fait exécuter à chaque machine la même simulation exacte. Si l'état initial est identique et les entrées identiques, les résultats restent identiques pour toujours. C'est le modèle lockstep, décrit dans l'article classique d'Age of Empires "1500 Archers on a 28.8".
Le lockstep repose sur le déterminisme : pour un état de jeu donné et un ensemble d'entrées donné, avancer d'un tick doit produire le même résultat sur chaque machine.
L'arithmétique en virgule flottante (la valeur par défaut dans la plupart des moteurs) est conforme IEEE-754 pour les opérations de base, mais n'est pas garantie reproductible bit à bit selon les processeurs, compilateurs, réglages d'optimisation, voire les builds de débogage et de production. L'étude de Glenn Fiedler sur le déterminisme en virgule flottante rassemble les récits de guerre : des fonctions transcendantes qui diffèrent entre AMD et Intel, des moteurs qui figent la précision de la FPU et le mode d'arrondi au démarrage, et des projets qui bannissent entièrement la virgule flottante du gameplay.
La réponse robuste est l'arithmétique à virgule fixe : des nombres stockés sous forme d'entiers mis à l'échelle, comme un format Q16.16 avec 16 bits pour la partie entière et 16 pour la fraction. La virgule fixe offre moins de plage et peut être plus lente que les flottants natifs, mais elle arrondit de manière prévisible et produit des résultats identiques partout. Les générateurs de nombres aléatoires doivent eux aussi être déterministes, initialisés de façon identique et avancés en lockstep pour que chaque tick obtienne les mêmes tirages. Les jeux échangent couramment des sommes de contrôle d'état pour détecter une désynchronisation dès qu'elle commence.
Le déterminisme n'est pas gratuit, et il est fragile. Toute dépendance cachée à l'ordre d'itération, au threading ou à un solveur physique tiers peut le briser. Mais il achète quelque chose de puissant : comme seules les entrées voyagent, la bande passante reste faible même avec des milliers d'unités.
Le délai d'entrée : la solution honnête la plus simple
La façon la plus directe de gérer la latence est d'attendre. Le délai d'entrée échantillonne l'entrée du joueur local et la retient quelques images avant de simuler, laissant le temps aux entrées distantes d'arriver. Le délai d'entrée est trivialement correct et n'a besoin d'aucune prédiction, mais le délai est réel et le joueur le ressent.
GGPO, le SDK de rollback pionnier, traite le délai d'entrée comme un cadran réglable plutôt qu'un coût fixe. Le guide du développeur suggère de choisir le nombre d'images retardées en fonction de la connexion, et avertit qu'un délai trop court produit des rollbacks plus longs et des glitches plus visibles. Délai et prédiction sont complémentaires, pas rivaux.
Pourquoi 'moins d'images retardées' n'est pas toujours mieux
Chaque image de délai d'entrée que vous supprimez doit être payée quelque part, généralement par des rollbacks plus longs quand une prédiction se révèle fausse. Le bon réglage dépend de la quantité de correction qu'un jeu donné peut masquer.
Rollback : prédire l'autre joueur
Le netcode à rollback est la prédiction côté client appliquée à tout le monde, pas seulement à soi. Chaque client simule immédiatement l'entrée du joueur local et devine l'entrée du joueur distant d'après ce qu'il a fait récemment. Il exécute l'image tout de suite au lieu d'attendre. Quand la véritable entrée distante arrive enfin, le client la compare à la conjecture. Si elles concordent, rien ne se passe. Si elles diffèrent, le client rembobine jusqu'au dernier état confirmé, substitue l'entrée correcte et re-simule toutes les images jusqu'au présent, généralement en une fraction d'image, bien plus vite qu'en temps réel.
La documentation GGPO formule l'objectif simplement : la conception vise à donner aux joueurs l'« illusion d'un réseau sans latence », afin que le timing, les réflexes et la mémoire musculaire acquis hors ligne se transposent en ligne. Le SDK a été créé en 2009 et a popularisé le rollback dans les jeux de combat; son auteur, Tony Cannon, a expliqué l'approche dans le magazine Game Developer.
Le rollback impose de dures exigences d'ingénierie à un moteur :
- La simulation du jeu doit être déterministe et sérialisable, il faut pouvoir sauvegarder et restaurer l'état complet du jeu.
- Elle doit pouvoir avancer d'une image sans la rendre, car le rollback peut exécuter plusieurs images cachées d'un coup.
- La simulation doit être séparée de la présentation, afin que les effets et les sons générés pendant un rollback puissent être différés jusqu'à l'image visible.
- Elle doit tourner sur un pas de temps fixe, pour qu'un taux de tick variable ne déforme pas le rejeu.
Le projet Slippi de la communauté Melee en est une démonstration bien connue : le rollback a été ajouté après coup à un jeu GameCube de 2001 tournant dans un émulateur, permettant aux joueurs de s'affronter à distance sans le délai d'entrée qu'exigeait le netplay basé sur le délai.
Le rollback n'est pas invisible. Si une prédiction était fausse, la correction peut provoquer un bref saut ou une « téléportation » à l'écran. Les jeux règlent cela avec un peu de délai d'entrée et en limitant la distance de leur spéculation. Dans Overwatch, Timothy Ford, de Blizzard, a décrit la prédiction des projectiles eux-mêmes pour que les roquettes paraissent instantanées, acceptant qu'une roquette mal prédite semble parfois disparaître.
Compensation de latence : rembobiner le serveur
Les shooters rendent généralement le serveur autoritaire et refusent de faire confiance aux clients, ce qui est bon pour la sécurité mais crée un nouveau problème. Pour lisser le jitter, les clients affichent les autres joueurs légèrement dans le passé. Quand vous visez et tirez sur ce que vous voyez, vous visez là où le monde du serveur était.
La compensation de latence résout cela en faisant rembobiner au serveur le monde jusqu'au moment où l'entrée du tireur a été générée. Il stocke un court historique de la position et des hitboxes de chaque joueur puis, lors d'un tir, ramène les autres joueurs là où le client du tireur les voyait et y teste l'impact. C'est pourquoi la compensation de latence est souvent appelée rembobinage côté serveur.
Le moteur Source de Valve a popularisé la technique, et sa documentation comme son code source montrent comment le serveur reconstitue un tick antérieur dans une fenêtre bornée. Riot décrit le même design pour VALORANT : « Quand le serveur apprend que vous avez tiré, il doit rembobiner l'état du monde jusqu'à ce que vous regardiez au moment où vous avez appuyé sur la gâchette afin de déterminer précisément si votre tir a fait mouche », a expliqué l'entreprise.
L'effet secondaire est réel et très débattu. Le rembobinage favorise le tireur, ce qui façonne une asymétrie propre au genre connue sous le nom d'avantage du peek : un attaquant qui tourne un coin peut voir et tirer sur un défenseur avant que le client du défenseur n'ait été informé que l'attaquant s'est déplacé. Comme la vue du défenseur sur l'attaquant est elle-même retardée, le joueur agressif obtient une fenêtre de temps de réaction supplémentaire. Les jeux bornent la fenêtre de rembobinage pour empêcher un joueur ayant un ping très élevé de tuer quelqu'un qui s'est déjà mis à couvert, et ils règlent le taux de tick et le routage pour réduire la fenêtre plutôt que la supprimer.
Le lockstep déterministe n'envoie que des entrées et fait confiance à chaque machine pour aboutir à la même réponse. Les shooters à serveur autoritaire ne font confiance à personne et le paient d'un monde rembobiné.
Taux de tick et interpolation d'instantanés
Le taux de tick d'un serveur est le nombre de fois par seconde où il avance la simulation. Un serveur à 64 ticks simule toutes les 15,6 ms; un serveur à 128 ticks toutes les 7,8 ms. Des taux plus élevés rendent l'enregistrement des tirs et les déplacements plus frais, mais le coût est linéaire : les ingénieurs de Riot ont écrit qu'exécuter une image à 128 ticks en 7,8 ms consommait sinon un cœur de CPU entier par partie, les forçant à optimiser jusqu'à un budget de quelques millisecondes pour que plusieurs parties partagent un hôte.
Les clients simulent rarement le monde entier eux-mêmes. Ils reçoivent des instantanés de l'état du serveur et en affichent une approximation fluide. L'interpolation d'instantanés, telle que la décrit Fiedler, met en tampon les instantanés entrants pendant un court délai et interpole entre les deux plus récents, échangeant un peu de latence supplémentaire contre de la fluidité. Le tampon doit être assez profond pour que la perte d'un ou deux paquets ne provoque pas de saccade; la règle empirique de Fiedler est environ le triple de l'intervalle entre paquets, puis réduite grâce à un débit d'envoi plus élevé. L'extrapolation (deviner à l'avance quand un instantané est en retard) est utilisée avec parcimonie, car la physique et les collisions rendent vite les conjectures fausses.
La même tension apparaît dans les shooters sous forme de command buffering. Le serveur conserve une petite file des mouvements d'un client pour pouvoir les jouer en douceur au lieu de prédire à sa place. Riot a documenté l'équilibre : trop peu de tampon et le serveur prédit les mouvements et émet des corrections; trop, et le jeu donne l'impression d'un ping élevé. La simulation tourne sur un pas de temps fixe découplé du taux de rafraîchissement, de sorte qu'un client à 30 fps et un serveur à 128 Hz avancent quand même la même horloge.
P2P, serveurs autoritaires et pourquoi les genres divergent
La topologie qu'un jeu choisit façonne tout le reste.
- Lockstep pair à pair (RTS classique) : chaque joueur envoie des commandes à tous les autres, et chaque machine simule le même monde. Il ne nécessite pas de serveurs dédiés et consomme très peu de bande passante, mais il ne va que aussi vite que le joueur le plus lent, exige des connexions directes que les pare-feu bloquent souvent, et donne à chaque client l'état complet du jeu, ce qui facilite la triche en lisant des informations que le joueur ne devrait pas voir.
- Rollback pair à pair (jeux de combat) : deux joueurs échangent leurs entrées et chacun simule les deux personnages localement. Un état petit et entièrement visible rend le déterminisme et la sérialisation gérables, et les fuites d'informations importent moins quand tout le match est déjà à l'écran.
- Client-serveur autoritaire (la plupart des shooters) : un serveur détient la vérité; les clients ne prédisent que leurs propres actions et affichent tous les autres à partir des instantanés du serveur. Il résiste à la triche, absorbe du matériel hétérogène et passe à l'échelle pour de nombreux joueurs, au prix de serveurs, de bande passante et d'infrastructure.
Le compromis de sécurité
L'autorité serveur est la position anti-triche la plus forte : un client piraté peut se mentir à lui-même, mais le monde du serveur est ce que vivent les autres joueurs. C'est pourquoi les shooters compétitifs centralisent l'autorité et acceptent de la payer en latence.
Mais la compensation de latence crée sa propre surface d'attaque. Comme le serveur fait confiance à la vue déclarée par le client pour l'enregistrement des tirs, un joueur peut délibérément induire ou simuler de la latence pour élargir son avantage du peek, une pratique connue sous le nom de lag switching ou d'abus de lag. Des bornes sur la fenêtre de rembobinage et sur l'ampleur avec laquelle la position d'un joueur peut être rembobinée constituent la défense standard, tout comme le traitement des connexions asymétriques comme suspectes.
Le lockstep déterministe a une histoire de sécurité plus subtile. Comme chaque client doit aboutir au même résultat, toute divergence peut être détectée, et une simulation altérée est repérée lorsque sa somme de contrôle ne concorde pas. Cela rend difficile le piratage des règles. Cela n'empêche en rien la triche par information, car l'état complet du jeu (y compris les positions ennemies) est déjà sur le client.
Réserves et problèmes ouverts
Rollback et prédiction ne sont pas des dissolvants universels. Ils exigent une sérialisation d'état bon marché et une simulation capable d'exécuter de nombreuses images plus vite qu'en temps réel; une simulation physique lourde avec un solveur lent peut simplement être incapable de re-simuler assez vite. Le déterminisme est facile à briser accidentellement et coûteux à maintenir entre plateformes et compilateurs. La compensation de latence échange l'équité contre les sensations, et favorise toujours celui qui tire.
Il y a aussi un problème de mesure. Les joueurs attribuent au « lag » des saccades causées par leur propre taux d'images, par le serveur ou par le jitter, et ces causes ont des correctifs différents. Les équipes instrumentent de plus en plus tout cela (timing des ticks, profondeur du tampon, temps d'aller-retour et jitter) et l'exposent aux joueurs pour que le diagnostic ne soit pas une conjecture.
Ce qu'il faut surveiller
Trois tendances devraient continuer de façonner ce domaine. Premièrement, davantage de jeux mélangent les modèles : des simulations autoritaires côté serveur intégrant des techniques de rollback, plutôt que de choisir une seule philosophie. Deuxièmement, le support des moteurs mûrit, avec des bibliothèques déterministes d'arithmétique à virgule fixe et des outils de rollback qui deviennent accessibles aux petites équipes incapables de construire un netcode de zéro. Troisièmement, la latence elle-même est attaquée au niveau de l'infrastructure, par le routage privé et le placement régional des serveurs, parce que la milliseconde la moins chère est celle qu'on n'a jamais à masquer.
Le fil conducteur est qu'un bon netcode est un ensemble de compromis délibérés, pas un algorithme unique. La prédiction achète la réactivité en risquant des corrections. Le déterminisme achète une bande passante minuscule en exigeant la perfection. La compensation de latence achète des tirs qui semblent équitables en rembobinant le temps. Comprendre quel coût un jeu accepte de payer est le moyen le plus rapide de comprendre pourquoi il se sent comme il se sent en ligne.








