
Netcode
Le netcode est l'ensemble des techniques réseau qu'un jeu multijoueur utilise pour maintenir la cohérence de la vue du match de chaque joueur malgré le délai qui les sépare. Il couvre ce que le serveur envoie et à quelle fréquence, ce que le client prédit entre-temps, et comment les désaccords sont résolus. C'est la couche que les joueurs ressentent sans la voir.
,
De quoi est fait le netcode ?
La majeure partie de ce que les joueurs appellent un mauvais netcode n'est qu'un symptôme, et la cause se situe généralement dans une couche différente de celle qui est incriminée. Cette page explique de quoi est fait le netcode, quels sont ses compromis et comment identifier la couche responsable.
Le netcode est le code réseau qui maintient la cohérence d'un match multijoueur entre des machines séparées de quelques millisecondes. Il ne s'agit pas d'un système unique. Il se divise en sept parties :
Transport : le protocole qui transporte les paquets, presque toujours UDP pour les jeux en temps réel.
Boucle de simulation : la fréquence à laquelle le serveur fait progresser le monde du jeu, le tick rate.
Réplication : quelles données chaque joueur reçoit, et à quelle fréquence, le taux de rafraîchissement (update rate).
Autorité : quelle machine a le dernier mot, généralement un serveur faisant autorité.
Modèle d'hébergement : l'endroit où s'exécute cette simulation.
Modèle de synchronisation : comment les machines restent en accord.
Masquage de la latence : la prédiction côté client, l'interpolation et la compensation du décalage (lag compensation).
Aucune partie de cette pile ne constitue une réponse complète. Chacune prend une décision et laisse le reste à ses voisins. Un tick rate élevé ne sert à rien sur une longue route. La prédiction ne sert à rien face à un paquet perdu.
Points clés de l'article
La latence a un seuil incompressible, et tout le reste s'accumule par-dessus : Le temps de trajet physique entre deux machines est le délai minimum qu'un jeu en ligne puisse avoir. Le routage, le tick rate, la fréquence de mise à jour et le traitement s'y ajoutent tous. Le netcode ne peut pas éliminer ce délai. Il peut seulement décider où les joueurs le ressentent.
Le chemin le plus court est rarement le plus rapide : Une connexion directe de pair à pair semble être la route la plus courte entre deux joueurs, mais les paquets traversent tout de même les FAI des deux joueurs et les itinéraires choisis par ces réseaux. Un serveur bien placé entre eux est souvent à la fois plus rapide et plus équitable.
La compensation du lag déplace le coût, elle ne l'efface pas : La compensation du lag rembobine le serveur pour que le tir d'un joueur à fort ping soit pris en compte, ce qui signifie que la cible peut être touchée après s'être mise à l'abri. La seule véritable solution est de maintenir des écarts de ping faibles, ce qui en fait un problème de matchmaking et de placement de serveur tout autant que de netcode.
Le tick rate est un budget temps : Le tick rate d'un serveur définit le nombre de millisecondes dont il dispose pour simuler chaque étape du jeu. Des taux plus élevés réduisent le délai et améliorent l'envoi des hit registrations, mais consomment plus de processeur et de bande passante. Un serveur qui dépasse son budget subit des saccades pour tous les participants du match.
Deux choix distincts, pas un seul : L'endroit où le jeu s'exécute (pair à pair, relais ou serveur dédié) et la manière dont l'état est partagé (lockstep, rollback ou réplication d'état) sont des décisions indépendantes. N'importe quel modèle de synchronisation peut fonctionner sur n'importe quel modèle d'hébergement.
Comment le netcode masque-t-il la latence sans la supprimer ?
Les données se déplacent dans le cuivre et la fibre à une vitesse finie, de sorte que le retard ne peut jamais être inférieur au temps de trajet entre deux machines. Le netcode ne peut pas changer cela. Ce qu'il fait, c'est choisir où le retard se manifeste.
Chaque technique de masquage de la latence a un prix :
La prédiction permet au client d'agir immédiatement sur sa propre commande, de sorte que le jeu semble instantané. Lorsque le serveur n'est pas d'accord, le client est corrigé.
L'interpolation affiche les autres joueurs légèrement dans le passé afin que leur mouvement paraisse fluide. Le coût est que vous les voyez avec un léger retard.
La compensation du décalage (lag compensation) rembobine le serveur vers ce que le tireur a vu, de sorte que le tir d'un joueur à ping élevé soit pris en compte. Dans son article de 2001, Yahn Bernier, alors développeur chez Valve, décrivait cet effet secondaire : lorsqu'« un joueur ayant un fort décalage tire sur un joueur ayant moins de décalage et réussit son tir, le joueur ayant moins de décalage peut avoir l'impression que le joueur décalé a d'une certaine manière 'tiré derrière un angle'. »
Chaque technique échange un artefact contre un autre. Toutes travaillent sur le retard qui leur est imposé.
Ce retard est défini par bien plus que la simple distance, et le développeur de jeux n'a aucun contrôle sur le reste. En 2015, l'équipe d'ingénierie de Riot Games expliquait que les fournisseurs de dorsales et les FAI « privilégient un itinéraire moins cher plutôt qu'un itinéraire plus rapide ». Sur une connexion reliant San Francisco à Portland, « un trajet direct aurait pu prendre 14 ms, mais l'itinéraire moins efficace prend un total de 70 ms ».
La distance définit le plancher, et le routage décide à quelle hauteur vous atterrissez par rapport à celui-ci. C'est le FAI qui prend la décision de routage, pas le développeur. Ce que le développeur choisit en revanche, c'est l'emplacement du serveur, ce qui détermine les itinéraires qui sont proposés.
Qui héberge la logique du jeu, et comment reste-t-elle synchronisée ?
Ce sont deux choix distincts, et n'importe quel modèle de synchronisation peut fonctionner sur n'importe quel modèle d'hébergement.
Qui héberge la logique du jeu (là où s'exécute la simulation) :
Peer-to-peer (pair-à-pair) : la machine d'un joueur héberge la partie. Ce joueur n'a aucun délai réseau, et tous les autres dépendent de la connexion de l'hôte. Voir peer-to-peer.
Relais : un serveur transmet les paquets entre les joueurs. Il n'exécute pas la simulation et ne valide rien. Voir serveur relais.
Serveur dédié : la simulation s'exécute sur une machine contrôlée par le développeur. Cela élimine l'avantage de l'hôte et offre à chaque joueur un point de connexion neutre. Le compromis réside dans le coût et la couverture, car les serveurs doivent être financés et être situés suffisamment près de chaque joueur. Voir serveur dédié.
Comment les machines restent d'accord (le modèle de synchronisation) :
Lockstep : les machines n'échangent que les commandes (inputs), et personne ne bouge tant que les commandes de chacun ne sont pas arrivées. Le délai d'entrée est égal à la latence, et la simulation doit être déterministe. Courant dans les jeux de stratégie.
Rollback : chaque machine prédit les commandes des autres et simule immédiatement. Lorsqu'une commande réelle diffère, le jeu revient en arrière et relance la simulation. Les contrôles semblent instantanés, au prix de corrections visuelles et d'un surcoût CPU. Standard dans les jeux de combat. Voir rollback netcode.
Réplication d'état : le serveur envoie des instantanés (snapshots) et les clients masquent le délai grâce à la prédiction, l'interpolation et la compensation du décalage (lag). Standard pour les jeux de tir. Voir réplication d'état.
Le délai d'entrée et le rollback sont les deux réponses à la même question : que doit afficher l'écran d'un joueur pendant que la commande d'un autre joueur est encore en cours d'acheminement ? La comparaison d'Edgegap sur le délai d'entrée par rapport au rollback détaille les cas d'utilisation de chacun.
L'hébergement détermine qui absorbe le délai. La synchronisation détermine comment cela se traduit visuellement. Aucun des deux ne détermine l'importance de ce délai.
Que veulent dire les joueurs quand ils parlent de « mauvais netcode » ?
Les joueurs signalent des symptômes. Ils désignent rarement une couche. Une même plainte peut provenir de plusieurs causes, et chaque cause nécessite un correctif différent.
Ce que les joueurs signalent | La couche généralement responsable | Terme |
|---|---|---|
Un tir touche après que la cible s'est mise à l'abri | La compensation de latence fonctionnant sur un écart de ping important | |
Téléportation et retour en arrière | Le serveur corrigeant un client qui a dérivé | |
Toute la partie saccade | Le serveur dépassant son budget de tick | |
Les personnages se figent en plein mouvement | Pertes de paquets | |
Un coup inflige plus de dégâts qu'une seule balle ne le devrait | Plusieurs tirs arrivant dans une seule mise à jour |
La dernière ligne correspond à la « super balle » que Battle(non)sense a décrite dans sa vidéo « Netcode 101 » de 2017. À 10 mises à jour par seconde, une arme tirant 750 balles par minute ou plus place deux balles ou plus dans une seule mise à jour.
La première ligne est liée au délai, et à la façon dont il se répartit de manière inégale entre les joueurs d'une partie. Aucune technique de netcode ne permet de contrôler cela. L'emplacement du serveur est le principal levier dont dispose un développeur.
Edgegap a testé le cas qui devrait le plus favoriser une connexion directe. Dans une analyse réalisée en 2020 sur 122 000 parties en pair-à-pair d'un jeu de console en 1v1, le fait d'acheminer chaque partie via un serveur placé au meilleur endroit disponible entre les deux joueurs a réduit le temps d'aller-retour moyen de 23 % dans 70 % des parties (étude de cas 1v1). Dans les 30 % restants, ce n'était pas plus rapide qu'une connexion directe. L'article d'Edgegap sur les fondements du netcode couvre l'intégralité du raisonnement.
Un mot de notre sponsor (nous-mêmes !)
La majeure partie du lag provient de la distance, non du code. L'Edge Cloud d'Edgegap est un réseau distribué disposant de plus de 615 emplacements disponibles sur demande, garantissant que chaque partie se déroule au meilleur endroit possible pour ses joueurs. Des tests indépendants sur le trafic d'un studio en direct ont mesuré une baisse de 58 % du temps de trajet aller-retour moyen par rapport au cloud public.
Où se situe le netcode de votre moteur ?
La couche réseau d'un moteur est l'interface sur laquelle un développeur s'appuie : Netcode pour GameObjects d'Unity, Mirror, Fish-Net, le réseau intégré d'Unreal, l'API multijoueur de Godot. Chacun d'eux implémente une partie de la pile, comme un transport, un moyen de répliquer l'état et, dans certains cas, la prédiction.
Aucun d'entre eux ne décide de l'endroit où s'exécute la simulation faisant autorité, ni de sa proximité avec chaque joueur. Ces deux choix se situent au-dessus de la bibliothèque, et ils définissent le délai que la bibliothèque doit ensuite masquer.
L'avis d'Edgegap (ce n'est que notre opinion, à prendre avec des pincettes !)
Le netcode masque la latence. Le placement décide de la quantité à masquer.
Quand un testeur dit que le netcode est mauvais, le premier réflexe est d'ouvrir le code de prédiction. Vérifiez d'abord quatre choses, dans cet ordre : l'écart de ping entre les joueurs de cette partie, la perte de paquets sur leurs connexions, si le serveur a respecté son budget de tick sous charge, et ce que disent les journaux de désynchronisation.
Seul le dernier point concerne directement le code que vous avez écrit. Les trois premiers concernent l'importance du délai et sa répartition entre les joueurs. Le netcode peut masquer le délai. Il n'a aucun pouvoir sur sa quantité à masquer.
Ajuster la prédiction pour compenser un long trajet traite le symptôme. Souvent, la cause réside dans l'endroit où le serveur est hébergé. Un serveur dédié lancé à proximité des joueurs d'une partie, sur un réseau disposant d'un choix suffisant d'emplacements, réduit le délai lui-même. Le netcode ne peut pas faire cela.
,










