- A propos
-
Half-life 2 » Dans ce nouvel épisode, vous incarnez de nouveau le scientifique barbu Gordon Freeman. L'histoire se déroule peu après que Gordon ait décidé de rejoindre l(...)
- Plus de news
-
Sam. 04 octobre
Les mods arrivent sur SteamVen. 03 octobre
VALVe regrette d'avoir employé le mot EpisodeSam. 27 septembre
Steam hébergera des mods dès la semaine prochaineSam. 20 septembre
Fortress Forever 2.1Jeu. 18 septembre
Garry's Mod à jour
- Nos partenaires
-
Neuf : 16,00 €
Occasion : 15,00 €
Ce jeu à -50 % sur PriceMinister7 € de réduction sur PriceMinister
avec le code AFFOLIE7PC
Lundi 19 septembre 2005 à 12 h 26, par niCO
NoFrag
Comment ça marche : le netcode de Source
e-t172
revient avec un nouveau
document sur les protocoles réseau de VALVe. Cette fois-ci, il
nous explique comment se déroulent les interactions entre le serveur
et le client quand vous jouez à HL2 ou Counter Strike :
Source.- Si vous voulez savoir comment certains joueurs se rendent plus difficilement touchables en modifiant leur fichier de configuration ;
- si vous ne comprenez pas pourquoi vous avez du choke avec votre connexion ADSL 20Mb ;
- si vous ne savez pas quoi utiliser comme rate/cmdrate/updaterate ;
- si vous possédez un serveur et que vous voulez l'optimiser ;
- si vous ne voyez pas l'intérêt de virer l'interpolation ;
- si vous croyez malin de ne pas utiliser la prédiction ;
- ou si vous êtes simplement curieux de savoir comment fonctionne un netcode moderne
Introduction
Half-Life 1 a été sujet à de nombreuses spéculations concernant son netcode et l'art d'optimiser ses paramètres. Ce "sac à rumeurs" n'a pas échappé à la deuxième version du moteur, à savoir le moteur Source.Aujourd'hui sur le net, à propos de ces "boîtes noires", on trouve des explications le plus souvent totalement contradictoires (l'une recommandant tel paramètre et l'autre exactement le contraire), tellement qu'aujourd'hui personne ne sait qui croire.
Ce document est une N + Nième interprétation du fonctionnement et des paramètres de ce Netcode. Mais, là où d'autres n'indiquent que les paramètres à définir ("tu règles ton cmdrate sur X, ton updaterate sur Y, tu verras ça va te booster ton jeu"), ce document est une tentative d'explication en profondeur et avec le plus de détails possible des principes directeurs du Netcode, de son fonctionnement, des techniques mises en oeuvre et des paramètres associés.
Au lieu d'appliquer des paramètres et de les tester en jeu, une technique qui dépend énormément des circonstances et de l'humeur du jour du testeur et difficilement objective, ce document présente une approche différente, tentant de découvrir ce sur quoi un paramètre précis influe, non pas à l'extérieur, mais à l'intérieur, ceci pour mieux comprendre ses véritables effets (secondaires ou non) sur la qualité du jeu. Le principe étant de partir des documentations officielles (Valve SDK), des tests "formels" (c'est à dire montrant l'influence de telle situation sur une valeur chiffrée, sur le netgraph le plus souvent) et, dans une moindre mesure, des faits communément admis (c'est à dire reconnus par la grande majorité des joueurs) pour en déduire d'autres faits qui eux-mêmes auront des conséquences sur le comportement du serveur ou du client.
A la lumière de cette introduction il apparaît que vous devez lire ce document avec un esprit critique. Toutes les thèses avancées ici ne sont pas forcément vraies. Il s'agit juste de réfléxions personnelles basées sur la documentation officielle. Pour les mêmes raisons, il est possible que le contenu de ce document soit sujet à variations en fonction de l'évolution de mes théories (voir la section Historique). Il est également possible qu'une partie de ce document contredise ce que vous avez lu ailleurs : à vous de vous faire une opinion.
Tick tac fait le serveur
Afin de comprendre comment communique le client et le serveur, il m'a paru nécéssaire d'étudier le fonctionnement de ce dernier afin d'en déduire la nature des échanges avec le client.Avant toute chose, rappellons que le serveur est le seul, parmi les parties mises en communication, à avoir la "vraie" vision du jeu. Il a priorité sur toute spéculation faite par le client. On dit que le serveur a autorité (server is authoritative en anglais) sur le jeu. Cela signifie que les différents clients ne communiquent jamais directement entre eux, il ne connaissent même pas l'adresse IP de leurs voisins : leur seul interlocuteur est le serveur.
Ticks et tickrate
Un tick est, dans une partie, une unité de temps élémentaire et indivisible. Il ne peut rien se passer entre deux ticks. Ce terme désigne une génération du monde par le serveur.Au cours d'un tick, le serveur récupère et analyse les informations envoyées par les clients quant à leur état. En partie grâce à ces informations, il va générer le "monde" : il détermine la position et l'état des joueurs et des différentes entités telles que les objets physiques (bidons...). Cette tâche est particulièrement ardue du fait de la complexité des éléments à gérer, surtout dans le cas du moteur physique. Une fois le monde généré, il envoie cette nouvelle vision de la partie aux clients connectés.
Le rôle principal du serveur est de générer constamment des ticks pour réagir aux actions des clients et des entités. Le nombre de ticks générés par seconde est appellé tickrate. Exprimé en ticks par seconde, il est en outre paramétrable par l'administrateur du serveur via le paramètre
-tickrate . Il est par défaut
réglé à 33 ticks par seconde, ce qui signifie que le monde sera
recalculé toutes les 30 millisecondes (1000 ÷ 33 ~= 30).
Augmenter le tickrate n'est pas sans contrepartie : en effet le serveur consommera plus de CPU et de mémoire vive. Pour éviter qu'une surconsommation n'aie des effets néfastes sur les joueurs, le tickrate est dynamique : ainsi, le serveur pourra passer d'un tickrate de 66 à un tickrate de 50 s'il il n'a plus assez de ressources pour tenir la charge imposée. Il convient donc de faire la différence entre le tickrate théorique, paramétré par l'administrateur, et le tickrate réel, qui est le tickrate sur lequel le serveur tourne en réalité à un moment précis. Nous verrons plus tard comment déterminer le tickrate réel d'un serveur.
Au niveau de la gestion des clients connectés, le serveur utilise des sockets dits "non bloquants", la boucle principale étant commandée par le tickrate. Pour cette raison il est absurde de dire qu'un joueur, de par sa connexion ou son ping, peut par sa présence avoir des conséquences négatives sur le jeu des autres joueurs. La consommation d'un serveur et donc son tickrate ne peuvent pas être affectés par la qualité de la connexion d'un joueur.
Les effets du tickrate
Nous allons prendre un exemple précis pour démontrer l'influence du tickrate sur la qualité du jeu.Nous sommes dans la situation suivante, dans le jeu Counter-Strike Source : un contre-terroriste se déplace du côté gauche de la vision d'un terroriste vers le côté droit. Le terroriste tire sur le contre-terroriste lorsque celui-ci est à mi-chemin de son parcours. On considère qu'il a bien visé et on fait abstraction de la précision de l'arme. La distance de déplacement du contre-terroriste est relativement minime pour mieux constater les effets du tickrate.
Situation "réelle"


Situation sur un serveur tickrate
33


Vous pouvez constater que à t = 15 ms, le serveur n'a pas généré de nouveau tick (puisque l'intervalle de tick est à 30 ms), donc le tir du terroriste n'est pas encore inclus et le contre-terroriste est toujours à sa position initiale. En revanche, à t = 30 ms, le serveur génère un nouveau tick et place le contre-terroriste à se position finale tout en incluant le tir du terroriste. Malheureusement, la balle de celui-ci ne touchera pas son but car pour le serveur le contre-terroriste est positionné après la balle : la position intermédiaire n'a pas été calculée.
Lorsque cette situation se produit, les joueurs utilisent en général l'expression "le serveur ne touche pas".
Situation sur un serveur tickrate
66


Sur un serveur de tickrate 66, l'intervale entre deux ticks est de 1000 ÷ 66 ~= 15 ms. Un tick supplémentaire est donc généré à t = 15 ms : la position intermédiaire est calculée, l'impact est bien pris en compte.
Vous devez cependant relativiser cet exemple : la situation n'est pas aussi dramatique qu'elle en a l'air sur un serveur tickrate 33, du fait que le rapport taille des hitboxes/distance parcourue est complètement différent.
FPS Serveur : la grande mascarade
Le serveur possède en plus du paramètre -tickrate une CVAR nommée fps_max, qui est décrite par le moteur comme étant le "frame rate limiter", soit le "limiteur de cadence d'images par seconde". Beaucoup de personnes pensent qu'augmenter ce paramètre améliore la qualité du serveur. Il n'en n'est rien. Explications.Vous vous demandez peut-être : "Mais pourquoi les frames existent-elles sur un serveur alors que cette fonction est remplie par le tick ?". Ce sujet du FPS a nécéssité l'ouverture d'un espace de travail dans lequel j'ai exposé durant quelques jours les données connues, mes hypothèses et les conclusions que je tirais. Cette recherche a porté ses fruits et je suis maintenant à même d'expliquer le concept de FPS serveur.
Pour bien comprendre, prenons un serveur non dédié, dit "listen". La particularité de ce type de serveur est qu'il y a le serveur et un client dans le même processus. Du coup, les ticks doivent se faire entre deux générations d'images (frames). Les développeurs ont donc été contraints d'enfermer la boucle des ticks dans la boucle des images générées. En plus clair, à chaque itération de la boucle des images, le jeu vérifie avec la valeur du tickrate si il doit générer un tick. Si la réponse est positive il le génère, dans le cas contraire il génère juste l'image sans tick.
Passons au cas du serveur dédié. Sur un tel type de serveur, aucune image n'a besoin d'être générée : seuls les ticks comptent. La boucle des FPS devient donc inutile et devrait logiquement être remplacée par une boucle des ticks. Eh bien non. La boucle des FPS est toujours là et suit le même principe que pour un serveur listen, à la différence qu'elle ne génère plus d'images mais uniquement des ticks. Pourquoi ? Une explication plausible est que les développeurs, dans un souci de maintenabilité du code, ont voulu garder la même architecture sur les serveurs listen que sur les serveurs dédiés. Ils ont donc simplement désactivé la partie client pour passer d'un serveur listen à un serveur dédié.
Etant donné que la boucle des FPS sur un serveur dédié ne génère plus d'images, augmenter la fréquence des itérations de cette boucle via la CVAR serveur fps_max ne changera strictement rien à la qualité du serveur, de même que sa consommation. En revanche, si vous la baissez en dessous de la valeur du tickrate théorique, le tickrate réel descendra à la valeur de fps_max : cela est dû au fait que les ticks sont toujours encapsulés dans la boucle des FPS.
Communication client/serveur
La communication client/serveur dans le jeu doit permettre deux choses :- Envoyer l'état des commandes (clavier et souris), c'est à dire les commandes éxécutées par le client, au serveur.
- Envoyer l'état actuel du jeu au client.
Note : le cmdrate et le updaterate dont on parle ici sont les valeurs réelles. Il s'agit du nombre de mises à jour que vous envoyez/recevez en réalité, non de la valeur des CVARs correspondantes.
La bande passante utilisée pour les mises à jour provenant du serveur (donc dont la fréquence est caractérisée par l'updaterate) est auto-limitable grâce à une fonctionnalité appellée rate.
Influence de l'updaterate/cmdrate et facteurs limitants
Vous pouvez déterminer votre cmdrate en cours de jeu en lisant la donnée correspondante du netgraph. Qu'est-ce qui limite cette valeur ?- La connexion avec le serveur.
- La CVAR
client
cl_cmdrate(par défaut 30) définissant le cmdrate maximum. - Le nombre de FPS affichées chez le client. Cette limitation qui peut paraître bizarre est dûe au fait que le client ne peut rien faire durant la génération d'une frame (donc ne peut pas envoyer d'informations); les commandes client sont donc envoyées entre les frames.
L'updaterate est lui aussi lisible sur votre netgraph. Qu'est-ce qui limite cette valeur ?
- La connexion avec le serveur. Ceci inclut le rate (voir plus loin). Notez que si ce facteur limite l'updaterate, du choke sera généré.
- La CVAR client
cl_updaterate(par défaut 20) définissant l'updaterate maximum - La CVAR serveur
sv_maxupdaterate(par défaut 60) définissant l'updaterate maximum - La CVAR serveur
sv_minupdaterate(par défaut 10) définissant l'updaterate minimum - Et bien sûr, le tickrate du serveur.
Le rate : auto-limitation de bande passante
Le rate, contrôlé par la CVAR client du même nom, limite la bande passante utilisée par le serveur pour envoyer les mises à jour au client (cela ne concerne pas le sens "client vers serveur"). Il est exprimé en octets par seconde.On pourrait penser que le rate est un dispositif destiné à ajuster automatiquement l'updaterate maximal de manière à ne pas dépasser une certaine limite de bande passante. Force est de constater qu'il n'en est rien : l'updaterate maximal ne bouge pas, ce qui provoque forcément des problèmes de choke en cas de rate trop bas pour la taille des mises à jour. Limiter le rate revient donc à "simuler" une connexion plus lente - ainsi, régler le rate à 5000 revient à jouer avec un modem 56K.
De ce fait, le rate n'est utile que lorsque l'on veut, pour une raison ou pour une autre, s'assurer que la bande passante consommée en récéption chez le client ne dépasse jamais une certaine valeur. Ce qui restreint l'utilisation de ce paramètre qu'à des cas très spécifiques. Limiter le rate force le jeu à sous-utiliser la connexion, ce qui n'a strictement aucun intérêt pour le commun des mortels. Cela signifie également que, contrairement à ce que beaucoup de monde pense, placer le rate à une valeur plus grande que la bande passante de votre connexion ne peut pas provoquer de problèmes de choke supplémentaires. Il convient donc de toujours placer la CVAR rate à sa valeur maximale, à savoir 81920 (qui correspond à 80 ko/s). Ces 80 ko/s ne seront en réalité atteints que rarement, la bande passante utilisée étant dans ce cas contrôlée par l'updaterate.
Pour ajuster la bande passante consommée par le jeu à son type de connexion (RTC, ADSL...), il est donc plus judicieux d'utiliser les CVARs de limitation de fréquence (cl_updaterate et cl_cmdrate), qui vous éviteront le choke. Voir à ce sujet la partie optimisation.
Une autre utilité du rate réside dans la CVAR serveur
sv_maxrate, qui limite la bande passante utilisable par
chaque client connecté à une valeur maximale, au risque de causer du
choke chez ceux-ci. Si vous voulez simplement diminuer les proportions
prises par la bande passante de votre serveur sans risquer de problème
de choke, penchez vous plutôt sur la CVAR
sv_maxupdaterate.Taille des mises à jour et compression
Une mise à jour totale indiquant la position et l'état de tous les joueurs et entités de la map "pèse" au minimum 1000 octets et peut facilement dépasser les 2000. Ces valeurs vous semblent ridicules ? Avec un updaterate de 66, donc en recevant 66 paquets de 2000 octets par seconde, on atteint 132 kilo-octets/seconde de bande passante consommée. Impensable.Pour résoudre ce problème, Source applique une compression de type delta aux mises à jour. En clair, il n'envoie que ce qui a changé depuis la dernière mise à jour reçue par le client (ou le serveur). Avec cette technique et en situation normale de jeu, la taille moyenne des paquets descend à environ 150 octets, ce qui est beaucoup plus supportable.
Cela dit, lors d'affrontements violents impliquant plus d'une dizaine de joueurs, les informations envoyées par le serveur (les différents sons produits et le mouvement des objets suite au souffle d'une grenade notamment) atteignent une taille telle que le choke est souvent inévitable.
Une question se pose : baisser votre updaterate diminue votre consommation de bande passante (et donc les risques de choke) en situation normale de jeu, mais pas lors d'affrontements, où la bande passante consommée ne varie quasiment pas. Pourquoi ?
Pour répondre à cette question, considérons le contenu des mises à jour en situation normale de jeu et comparons-le à des mises à jour en situation d'affrontement.
En situation normale, le contenu des paquets se résume à des déplacements de joueurs et aux tirs éventuels. Imaginons qu'un joueur se trouve au point A et se dirige vers le point C en passant par le point B. Avec un updaterate haut, le serveur va envoyer au client un paquet disant que le joueur se trouve au point A, puis un autre rapportant qu'il se trouve au point B, et enfin un autre pour le point C. Trois paquets. Avec un updaterate bas, le serveur va seulement envoyer deux paquets au client : le point A et le point C, en faisant abstraction du point B (le serveur a en réalité bien calculé ce point - du moins si son tickrate est suffisant - mais ne l'envoie pas au client). Résultat : deux paquets au lieu de trois donc économie de bande passante.
Passons au cas d'affrontements. Ici les paquets sont plus de 10 fois plus lourds qu'en situation normale. Les déplacements et les tirs ne constituent plus qu'un petit coin de chaque paquet : les sons et les informations du moteur physique prennent tout le reste. Or le problème est que ces informations sont spontanées et indivisibles, donc non compressibles selon la technique présentée au paragraphe précédent. Baisser l'updaterate ne provoque donc que peu d'économie de bande passante dans ces situations. En réalité, le serveur enverra effectivement moins de mises à jour, mais celles-ci seront plus lourdes.
Les mises à jour et le ping affiché
Chaque partie mise en communication, c'est à dire le serveur ou votre client, calcule la latence selon un procédé qui pour l'instant m'échappe. J'ai néanmoins réussi à découvrir que la partie qui détermine le ping le calcule sur les paquets qu'il reçoit : ainsi, le ping déterminé par le serveur (affiché par le tableau des scores) est calculé sur les mises à jour envoyées par le client, tandis que le ping déterminé par le client (affiché dans le netgraph) est calculé sur les mises à jour reçues par le client.Il vous est peut-être déjà arrivé de constater que si vous mettiez votre CVAR
cl_cmdrate à des valeurs très basses (telles
que 5 par exemple), votre ping dans le tableau des scores tombait à un
niveau ridiculement bas. En réalité, votre latence n'est pas
diminuée. En aucun cas votre ping réel ne peut passer en dessous du
ping que vous auriez en utilisant ICMP (c'est à dire la commande
"ping"). Il est même possible que ce problème de calcul touche
aussi le lag compensation, auquel cas vous n'auriez pas du tout
intérêt à essayer.
Il semblerait en fait que, de par le fait que le ping est calculé sur les paquets reçus, le serveur donnerait un ping faux sur des valeurs de cl_cmdrate trop basses. Les calculs commenceraient à "dérailler" à partir de 30 pour cl_cmdrate (tableau des scores) et 20 pour cl_updaterate (netgraph).
L'explication précise de ce phénomène m'échappe encore.
Loss, choke et compagnie : non, tout n'est pas rose
Il arrive souvent que le netcode ne fonctionne pas de façon optimale. Cela peut être dû à de mauvais paramètres ou, plus souvent, à une connexion de qualité insuffisante. Deux problèmes peuvent se produire : l'apparition de loss ou de choke.Le loss
Le loss n'est pas un phénomène compliqué : il signifie tout simplement que des paquets de données n'arrivent pas à destination. Il y a donc de la perte. Ce problème ne peut se produire qu'à cause d'une connexion instable, ou dans le cas d'un choke très élevé.A priori, le calcul du loss s'effectue en vérifiant les numéros de séquence des mises à jour : si le jeu reçoit les mises à jour 1 et 3 mais pas la mise à jour 2, il y a un paquet perdu.
Un loss faible n'aura pas beaucoup d'impact sur votre jeu : perdre 5 mises à jour sur 100 par exemple n'est pas dramatique. Pour les mises à jour client vers serveur, chaque paquet envoyé contient un "historique" des commandes précédentes pour éviter que le serveur ne "loupe" votre tir par exemple.
Le choke
Nous avons vu dans la section sur les mises à jour que le serveur envoyait les informations sur le jeu en cours à une certaine fréquence appellée updaterate et exprimée en mises à jours par seconde.Avec un updaterate de 66, les mises à jour sont envoyées par intervalles de 15 millisecondes. Il faut donc que chaque mise à jour soit transmise dans un délai maximum, une "fenêtre de transmission" de 15 millisecondes. Que ce passe-t-il si le délai de transmission d'un paquet dépasse cette fenêtre ?

En situation normale, les mises à jour gardent toujours un "intervalle" entre elles. Mais si la transmission d'une mise à jour est trop longue, celle-ci "déborde" de sa fenêtre : c'est le choke. Et si le problème persiste, la situation dégénère en une sorte de "réaction en chaîne" que vous pouvez voir sur le schéma (la zone rouge augmente de taille). Le principal problème causé par ce phénomène est que l'updaterate baisse et, surtout, les mises à jour arrivent avec de plus en plus de retard. La partie peut rapidement devenir injouable.
Ce "débordement" est dû à un manque de bande passante pour transmettre les mises à jour, qui lui même peut avoir deux causes :
- Votre connexion n'a pas une bande passante suffisante pour tenir le rythme du jeu (assez rare, sauf pour les 56K).
- La taille des paquets est trop grande.
Vous êtes en droit de vous demander comment votre connexion à 8 mbps (voire 25 mbps) pourrait avoir peur de 330 ko/s là où elle en supporte beaucoup plus. Malheureusement, le moteur Source souffre ici d'une limitation de taille. Pour rappel, le rate limite la bande passante utilisée par le serveur lors de l'envoi de ces mises à jour. Or, cette valeur a comme valeur maximale 81920, soit 80 ko/s... Conclusion, un paquet dont la taille dépasse 81920 ÷ updaterate (soit 1241 octets pour un updaterate 66) provoquera un choke inévitable : vous ne pouvez absolument rien faire pour résoudre le problème. La seule solution est d'attendre que Valve fasse sauter cette limitation, ce qui n'est pas Gagné d'avance. Cela dit, il est possible que le serveur limite votre rate (
CVAR
sv_maxrate); si c'est le cas, retirer cette limite devrait
diminuer les problèmes de choke sur les clients.
Si vous avez du choke en situation normale de jeu, baisser votre updaterate (via la
CVAR cl_updaterate) peut
améliorer votre situation. En revanche, le seul moyen d'éviter ce
problème lors des affrontements (rushs...) est d'améliorer votre
connexion avec le serveur (voir le problème des données ponctuelles);
si votre connexion supporte déjà plus de 80 ko/s (et côté serveur
également), vous ne pouvez rien faire.Les mécanismes de compensation réseau
Le jeu en réseau souffre de nombreuses contraintes dûes à la nature même de ces réseaux, peu adaptés à cette utilisation nécéssitant de délivrer des paquets de données à fréquence fixe avec une latence minimale. Cela est surtout vrai pour les connexions RTC et les connexions ADSL dénuées de la technologie FastPath.Pour cette raison, il a fallu développer des mécanismes "artificiels" pour compenser ces limitations. Pour le moteur Source, 3 de ces mécanismes sont implémentés : l'interpolation et la prédiction côté client, et le lag compensation côté serveur.
La prédiction
Il s'agit du mécanisme le plus simple. Il a pour objectif de rendre le jeu plus "réactif" aux actions du joueur et est implémenté côté client.Sans la prédiction, le client affiche ce qu'il reçoit du serveur par les mises à jour et uniquement cela. Ce qui signifie que si vous tirez, le jeu ne déclenchera l'animation et les effets correspondants que lorsqu'il aura reçu confirmation de ce tir par le serveur. Cela nuit considérablement à la jouabilité car entraîne un décalage entre le moment où vous tirez et le moment où vous voyez ce tir sur l'écran.
Pour éviter ce problème, le jeu va anticiper la confirmation du serveur : c'est la prédiction. En clair, le jeu va tirer sans attendre la confirmation. Ce qui signifie que lorsque vous voyez l'animation de tir de votre arme, le tir a en réalité été pris en compte quelques millisecondes plus tard sur le serveur (votre latence), ce décalage étant compensé par le lag compensation que nous verrons plus tard.
La prédiction est surtout utile sur les actions de tir et de déplacement. Mais il peut arriver que cette "anticipation" ne soit pas correcte et que l'action ne se produise pas sur le serveur (ou d'une manière différente). Cela arrive notamment si vous tirez et que quelqu'un vous tue pendant le trajet de l'information de tir jusqu'au serveur : en réalité, votre tir n'a pas été pris en compte. Ces différences entre ce que le client s'attend à recevoir et ce qu'il reçoit réellement sont appellées erreurs de prédiction. Elles sont visibles grâce à la
CVAR cl_showerror (uniquement si
sv_cheats est à 1 sur le serveur). Le client se replacera
alors sur l'état indiqué par le serveur (puisque celui-ci a autorité
sur le jeu). Ces erreurs de prédiction arrivent en général peu
fréquemment, et leurs conséquences sont souvent négligeables.
Lorsque l'erreur de prédiction est minime (une très légère différence de direction lors d'un déplacement par exemple), votre client va "smoother" c'est à dire "adoucir" la correction de l'erreur. Par exemple, si la prédiction d'un de vos mouvements s'est fait légèrement trop à droite par rapport à la confirmation du serveur, votre jeu vous replacera "doucement" vers la bonne position, de sorte que vous ne vous en rendrez même pas compte.
Si l'erreur est grande (c'est à dire lorsque le temps nécéssaire pour "l'adoucir" dépasse la valeur de la CVAR client
cl_smoothtime), le client va vous replacer brutalement à
la bonne position : c'est ce phénomène que vous pouvez voir quand vous
revenez brusquement un pas en arrière au cours d'un rush par exemple
(un ami appellait ça des phénomènes de "back-vidéo").
La fréquence et la gravité des erreurs de prédiction dépend de votre latence et de la fréquence de vos mises à jour (dans les deux sens), ainsi que de la qualité du serveur.
La prédiction est désactivable avec la
CVAR
cl_predict. Cependant, cela ne présente aucun
intérêt.L'interpolation
Par défaut, votre updaterate ne peut pas dépasser 20 (cl_updaterate). Ce qui signifie que vous recevrez, pour
un joueur précis, 20 fois sa position par seconde.
Si il n'y avait pas d'interpolation, ce joueur, lors de ses déplacements, changerait de position 20 fois par seconde sur la vue du client, ce qui équivaut à avoir 20 images par seconde de ce joueur. D'où des saccades d'affichage. Et augmenter l'updaterate ne corrige pas grand chose dans la plupart des cas, vu que ces saccades seront dans ce cas dûes au cmdrate trop faible du joueur que vous regardez.
L'interpolation va "inventer" des points du joueur situés entre deux positions. Ainsi, si vous avez 85 images par seconde lorsque vous jouez et que le joueur que vous regardez change 20 fois de position par seconde, 65 points seront "inventés" par l'interpolation pour fluidifier son mouvement.
L'interpolation s'effectue sur un intervalle de temps fixe réglable avec la
CVAR cl_interp (en secondes, 0 pour
désactiver l'interpolation). Par défaut, l'interpolation
s'effectue sur 100 millisecondes (cl_interp 0.1).
L'interpolation induit donc forcément un décalage de temps entre la vue du client et les mises à jour que celui-ci reçoit, compensé par le lag compensation que nous verrons plus tard.
interpolation et cmdrate : le problème de la "touchabilité"
L'interpolation invente des points qui n'existent pas. Le fait que ces points n'existent pas peut être dû à votre updaterate trop bas, dans ce cas le serveur aura plus de points que vous sur le déplacement d'un joueur précis.
Mais imaginons que l'interpolation se fasse sur le mouvement d'un joueur dont le cmdrate est plus bas que le tickrate du serveur (par exemple un joueur avec le cmdrate par défaut 30 et un serveur de tickrate 66). Le client va inventer des points qui n'existent pas pour le serveur. Ce fait qui paraît logique (et qui l'est) peut avoir des conséquences néfastes sur la "touchabilité" d'un joueur, c'est à dire vos chances de l'abattre lorsque celui ci est en mouvement. En effet, si vous tirez sur une hitbox "inventée" par l'interpolation, c'est à dire ne correspondant pas avec sa position réelle sur le serveur, vous ne la toucherez pas car sa position réelle est différente.
Imaginons une situation similaire à celle prise comme exemple pour le tickrate : un contre-terroriste se déplace dans le champ de vision d'un terroriste. Celui-ci lui lui tire dessus à mi-chemin. On fait abstraction du lag et du décalage induit par l'interpolation, tous deux compensés par le lag compensation. On considère également que le tickrate du serveur est supérieur à 40 et que l'updaterate ainsi que le cmdrate du terroriste sont également supérieurs à 40.
Nous allons comparer plusieurs situations où on fait varier le cmdrate du contre-terroriste ainsi que l'interpolation.
Avec un cmdrate de 40
(intervalle : 25 ms), interpolation activée


Avec un cmdrate de 20
(intervalle : 50 ms), interpolation activée


Comme vous pouvez le voir, la position du contre-terroriste à 25 ms a été interpolée en raison de son cmdrate trop faible : le joueur a tiré sur un point qui n'existe pas sur le serveur, l'impact n'est pas pris en compte.
Avec un cmdrate de 20
(intervalle : 50 ms), interpolation désactivée


L'interpolation étant désactivée, le terroriste voit le contre-terroriste à la même position à 0 comme à 25 ms, c'est à dire la position réelle du contre-terroriste : il tire sur cette position et l'impact est bien pris en compte.
NOTE : comme pour le tickrate, cet exemple doit être relativisé. En effet le rapport taille des hitboxes/distance parcourue présenté ici est totalement différent.
Nous sommes donc dans la situation suivante : si le tireur a l'interpolation activée, plus l'adversaire aura un cmdrate bas, moins celui-ci sera "touchable" par le tireur. Mais ce cmdrate bas peut aussi entraîner des effets néfastes :
- Si le terroriste est immobile et que le contre-terroriste est en mouvement (notre exemple), le cmdrate bas du contre-terroriste lui sera profitable car il diminuera la "touchabilité" du terroriste.
- Si le terroriste et le contre-terroriste sont immobiles, le cmdrate du contre-terroriste ne joue pas.
- Si le terroriste est en mouvement et que le contre-terroriste est immobile, le contre-terroriste sera pénalisé par son cmdrate bas, car il enverra à une fréquence plus basse ses informations de tir pour toucher le terroriste en mouvement.
La meilleure solution pour éviter de se faire avoir par un cmdrate bas est donc de désactiver l'interpolation (
cl_interp 0). L'affichage des entités et des joueurs
sera alors plus saccadé mais retranscrira exactement le contenu des
mises à jour, donc tous les points affichés seront les mêmes que sur
le serveur.Le lag compensation
Il nous reste un problème à résoudre, fondamental dans les jeux en réseau : la latence. En effet, tirer sur un joueur en mouvement avec un ping de 80 ms sans mécanisme de compensation adapté oblige à viser au-devant de l'ennemi, ce qui n'est pas vraiment satisfaisant du point de vue de la crédibilité de la simulation.Alors comment le serveur fait-il pour compenser cette latence ? Eh bien il remonte le temps. En effet, tout le principe du lag compensation consiste à estimer à quel moment le joueur a réellement tiré (ou plus précisément : le moment auquel l'image sur laquelle le joueur a tiré s'est affichée). Une fois ce moment déterminé, le serveur va remonter dans un "historique" des précédents ticks. Une fois le tick correspondant isolé, il va l'utiliser pour déterminer si, dans cette "image du jeu", le joueur a touché son adversaire ou pas.
Avant de continuer, rappellons que la latence (le ping) est exprimé dans un délai aller et retour. Quels éléments le serveur doit-il prendre en compte lors de l'estimation du décalage entre le serveur et le client ?
- Le temps d'arrivée des mises à jour serveur vers client.
- L'interpolation (si elle est activée), qui crée un décalage supplémentaire.
- Le temps d'arrivée des commandes client.

Dans l'exemple ci-dessus (tickrate 66), le joueur a tiré alors qu'il voyait une mise à jour générée au tick 1. Au moment où il a "vu" ce tick, il était déjà en décalage avec le serveur de 140 ms (temps d'arrivée de la mise à jour + interpolation). Ajoutons à cela les 40 ms pour le parcours de la commande et on obtient 140 + 40 = 180 ms à remonter. Le décalage maximal compensable par le serveur est paramétrable avec la
CVAR sv_maxunlag (en secondes, par
défaut 1).
Le serveur sait qu'il y a 180 ms il en était au tick 1, donc il se sert de ce tick pour déterminer si le joueur a touché sa cible ou non. Si oui, l'impact est comptabilisé pour le tick 13.
Le lag compensation est désactivable avec la
CVAR
sv_unlag. Cependant le faire est très fortement
déconseillé.Le netgraph, une mine d'informations
Afin de tester la qualité de votre connexion et de vous fournir des infos utiles sur ce qui se passe, Source vous offre un outil très pratique : le netgraph.Une fois activé, celui-ci s'affiche dans un coin de votre écran pendant votre jeu et vous renseigne en permanence sur l'état actuel du Netcode.
Les différents modes de Netgraph
Le netgraph s'active avec laCVAR net_graph, qui peut prendre 4 valeurs
différentes. Pour toutes ces valeurs, le netgraph affichera vos FPS,
votre ping, la taille des paquets que vous envoyez/recevez, la bande
passante consommée dans les deux sens et votre
updaterate/cmdrate.- net_graph 1 : affiche en plus un graphique en bas dont je n'arrive pas à saisir la signification. Il est tout le temps plat...
- net_graph 2 : affiche en plus un graphique indiquant la taille des paquets que vous recevez en temps réel.
- net_graph 3 : affiche en plus vos valeurs de loss/choke.
Interpréter le netgraph
Il se lit de cette manière, de gauche à droite et de haut en bas :
Première ligne : votre nombre de FPS et votre latence actuelle.
Deuxième ligne : la taille du dernier paquet reçu, la bande passante consommée en récéption, et votre updaterate réel.
Troisième ligne : la taille du dernier paquet émis, la bande passante consommée en émission, et votre cmdrate réel.
Quatrième ligne (uniquement en net_graph 3) : votre valeur de loss (a priori exprimée en pourcentage de paquets perdus) et votre valeur de choke (a priori exprimée en unité arbitraire)
Notez que en net_graph 1 et 3, deux valeurs supplémentaires apparaissent : en haut la valeur de la
CVAR cl_updaterate
et en bas celle de cl_cmdrate.

Ce graphique disponible en net_graph 2 vous donne des informations sur les paquets que vous recevez. Une colonne du graphe signifie un paquet. La hauteur de la colonne symbolise la taille du paquet, et les différentes couleurs désignent le type des informations contenues dans le paquet (leurs significations m'échappent pour le moment).
La vitesse de défilement de ce graphe symbolise votre updaterate réel. Un "trou" signifie soit du loss, soit du choke.
Configurez votre netgraph
Le netgraph possède des paramètres modifiables dont je fais la liste ici :- net_graphpos : position horizontale du netgraph. 1 : gauche, 2 : droite et 3 : centre.
- net_graphheight : position verticale du netgraph en pixels. Ne concerne pas le graphe inférieur qui, lui, restera toujours collé au bas de l'écran.
- net_scale : échelle du graphe supérieur.
Optimisez !
Toutes les informations que vous venez d'ingurgiter à la lecture de ce document vont maintenant nous permettre de déterminer les meilleurs paramètres précis pour améliorer la qualité du jeu.Nous avons ici trois cas de figure : vous êtes administrateur de serveur et vous cherchez à améliorer la qualité du jeu chez les joueurs, vous êtes vous même joueur et vous cherchez les meilleurs valeurs possibles, ou encore vous cherchez à déterminer la qualité d'un serveur précis.
Administrateurs
Le serveur est la pièce maîtresse de toute partie de jeu en réseau. Pour cette raison, une configuration optimale de ce serveur peut considérablement améliorer la qualité du jeu chez les clients connectés.Le tickrate ne vous mordra pas
Comme nous l'avons dit, le tickrate est dynamique. Ce qui signifie que si votre serveur de jeu est la seule chose qui tourne sur la machine, vous avez tout intérêt à régler d'office le tickrate à 100. Il s'adaptera ensuite aux capacités réelles de la machine.
La situation est plus compliquée sur un serveur mutualisé, où vous devez aussi faire attention aux ressources des autres serveurs de jeux hébergés sur la même machine. Dans ce cas, vous allez devoir faire des tests.
Le tickrate est de loin la caractéristique la plus importante pour la qualité d'un serveur de jeu. Un serveur tenant un tickrate 100 à pleine charge peut être considéré comme quasi parfait.
Ne limitez rien si vous ne manquez de rien
Si vous vous contrefichez de la bande passante consommée par votre serveur, vous pouvez placer les CVARs
sv_maxrate et
sv_maxupdaterate à 0.
Si vous souhaitez simplement diminuer les proportions de bande passante prises par le serveur, utilisez en priorité la
CVAR
sv_maxupdaterate.
Enfin, si vous souhaitez vous assurer que la bande passante consommée pour chaque client ne dépasse jamais une certaine limite, utilisez la
CVAR sv_maxrate. Il est conseillé de l'utiliser
conjointement avec sv_maxupdaterate pour éviter les
problèmes de choke avec les clients ayant un updaterate
haut.
Contrecarrer les petits malins du cmdrate
J'ai expliqué dans la section sur l'interpolation qu'un cmdrate bas rendait un joueur moins touchable. Cet état de fait porte préjudice aux joueurs lambda qui ne sont pas forcément au courant qu'il vaut mieux désactiver l'interpolation pour éviter de tomber dans le panneau.
Le serveur ne dispose pas de
CVAR sv_mincmdrate, et
c'est bien dommage. Pour résoudre le problème, vous devrez utiliser
des plugins serveur (Mani Admin Plugin par exemple) pour forcer la
valeur de CVARs chez le joueur. Vous pouvez appliquer deux politiques
:- Forcer
cl_cmdrateà une valeur minimale. Atténue fortement le problème mais ne le fait pas disparaître complètement; de plus, peut causer des problèmes chez les joueurs ayant des connexions lentes. - Forcer
cl_interpà 0 pour couper l'interpolation chez tout le monde. Plus souple mais possède l'inconvénient de choisir pour les joueurs entre touchabilité et fluidité graphique sans leur demander leur avis, et surtout pénalise tout le monde pour contrecarrer les agissements d'une minorité.
Joueurs
Vous êtes joueur et souhaitez bénéficier des meilleurs paramètres possibles ? Suivez le guide !interpolation et rate
Vous devriez désactiver l'interpolation en plaçant la
CVAR cl_interp à 0 pour contrecarrer les "petits malins
du cmdrate".
Placez votre rate à 81920, c'est à dire la valeur maximale, même si votre connexion ne va pas jusque là : le placer plus bas n'a d'intérêt dans aucun cas.
cmdrate et updaterate
Là, c'est un petit peu plus compliqué. Vous allez devoir utiliser votre netgraph pour trouver les bonnes valeurs par tâtonnement.
Tout d'abord, placez votre cmdrate et votre updaterate tous deux à 100. Puis observez votre netgraph en situation normale de jeu (c'est à dire en dehors des affrontements tels que les rushs de début de partie) : si vous avez du choke, baissez votre updaterate et votre cmdrate progressivement jusqu'à ne plus en avoir, en essayant de les baisser séparément puis ensemble. L'objectif est d'obtenir les valeurs les plus hautes possible sans choke.
Notez qu'avec un serveur doté d'une connexion potable et d'une connexion ADSL 1 mbps, vous devriez pouvoir rester à 100 pour les deux CVARs sans aucun problème.
Il est possible que des valeurs optimales avec un serveur précis ne le soient pas avec un autre, voire même à certaines périodes et pas d'autres. Cela est dû au fait que la bande passante consommée augmente avec le nombre de joueurs présents sur le serveur et avec le tickrate (si votre updaterate/cmdrate est au dessus du tickrate pour ce dernier cas).
Notez également que la présence de choke lors d'affrontements violents est inévitable comme expliqué dans la section correspondante.
Déterminer la qualité d'un serveur
Il y a plusieurs raisons pour lesquelles on voudrait tester la qualité d'un serveur : pour un administrateur, cela permet d'apprécier la qualité du boulot, et pour un joueur, cela permet de choisir des serveurs de bonne qualité pour y jouer.Il y a trois éléments pour déterminer la qualité d'un serveur : son ping, sa bande passante et son tickrate réel. Le premier est visualisable très facilement, le deuxième se teste en "tâtant" le choke pour des valeurs d'updaterate hautes, mais le troisième est un peu plus subtil. Notre objectif ici sera donc de chiffrer ce tickrate réel.
Pour cela, il vous faut vous connecter au serveur. Ensuite, essayez d'obtenir les réglages d'updaterate les plus hauts possibles sans choke (chose que vous avez peut-être déjà faite, voir l'optimisation joueur). Ensuite lisez l'indication d'updaterate réel sur le netgraph. Il y a trois cas possibles :
- Votre
updaterate plafonne à la valeur de
cl_updaterate: votre connexion est trop lente pour tester la qualité du serveur. Vous pouvez néanmoins affirmer que le tickrate est supérieur ou égal à votre updaterate actuel. - Votre updaterate
plafonne à une valeur précise située en dessous de votre
cl_updaterate: la valeur affichée est soit la valeur desv_maxupdateratesur le serveur, soit le tickrate réel. Si vous ne connaissez pas la valeur desv_maxupdaterate, vous pouvez affirmer que le tickrate réel est égal ou supérieur à la valeur affichée. Sisv_maxupdaterateest au-dessus de la valeur affichée ou est illimité, vous avez le tickrate réel. - Votre updaterate plafonne à 100 : le serveur est "quasi-parfait" (tickrate réel égal ou supérieur à 100).
Le bug des hitboxes : mythe ou réalité ?
Aujourd'hui beaucoup de personnes ne veulent pas passer à Source. Ceci à cause d'un bug qui serait présent dans le moteur : le fameux bug des hitboxes. Concrètement, ce bug consiste en un décalage vers l'avant des hiboxes d'un joueur par rapport à la position réelle de ce dernier lorsque celui-ci est en déplacement.J'ai visionné une vidéo qui montre le bug, et une autre expliquant pourquoi elle n'est pas crédible (dont j'ai malheureusement paumé le lien). Ce qui me rend initialement neutre. Voici les 3 réponses que j'ai pu voir des prétendants au "y'a pas de bug" :
- Cette vidéo est très vieille, le bug a été corrigé depuis.
- Les démos ont un bug de prédiction qui fausse les résultats.
- Enfin, les
hitboxes apparaissant décalées sont dûes au fait que la
CVAR sv_showhitboxesmontre les hitboxes du serveur et non du client.
Nous allons tout d'abord lancer un serveur local, puis activer l'affichage des hitboxes avec la commande
sv_showhitboxes
2.
Nous allons ensuite multiplier par 10 le temps d'interpolation (
cl_interp 1) pour déterminer si les hitboxes affichées
sont celles du serveur ou du client. Verdict :

Les hiboxes sont très décalées : les hitboxes affichées sont celles du serveur, et non du client comme le supposait la vidéo. A quoi cela nous avance ? Eh bien le fait que ces hitboxes soient décalées est tout à fait normal : cela est dû au lag (latence + interpolation). Ce décalage est compensé par le lag compensation que nous avons vu plus haut.
Vérification : mettons
cl_interp à 0 - on constate que
les hitboxes ne sont plus décalées.
On peut aussi faire le même type de tests en simulant de la latence grâce à la
CVAR net_fakelag : là aussi, les hitboxes sont
plus décalées que la normale.
Nous allons maintenant "ralentir le temps". Cela nous permettra de tester plus facilement les effets du tir lorsque l'on vise les hitboxes, le model ou juste devant le model. Pour cela, faites host_timescale 0.2.
Essayez ensuite, avec différentes valeurs de
cl_interp
ou de net_fakelag, de tirer sur les hitboxes serveur, sur
le model ou devant le model : seul le model est touchable. Le lag
compensation fait très bien son boulot.
Conclusion : le bug des hitboxes a probablement existé, mais n'est plus effectif aujourd'hui.
Questions sans réponse
Mon document n'est malheureusement pas exhaustif. En effet je n'ai pas trouvé le moyen de répondre à certaines des questions que je me suis posées. Lesquelles sont :- Que représente le graphique du bas dans le netgraph ?
- La
CVAR fps_maxsur le serveur sert-elle vraiment à quelque chose ? Si oui, comment fonctionne-t-elle ? Comment un serveur peut-il avoir une notion de FPS alors que cette fonction est comparable au tickrate ? - Baisser son
cmdrate avec la
CVAR cl_cmdratefait baisser le ping dans le tableau des scores, mais pas dans le netgraph. Quelles sont les différences entre le calcul du ping affiché dans le tableau des scores et le calcul du ping affiché sur le netgraph ? Pourquoi abaisser le cmdrate a-t-il cet effet secondaire alors que la véritable latence ne descend vraisemblablement pas ? Cette "soi-disant" descente de ping a-t-elle un impact sur le calcul du lag compensation ou celui-ci utilise-t-il l'algorythme de calcul du netgraph ? - Qu'est ce que la CVAR serveur
sv_alternateticks? Que désignent ces "alternate ticks" ? S'agirait-il d'une sorte d'interpolation côté serveur ? - Qu'est ce que la CVAR serveur
sv_lagflushbonecache("Flushes entity bone cache on lag compensation") ?
Un grand merci à l'auteur qui nous a permis de recopier son document :
- e-t172
- E-mail : mail.et172*gmail*com
- MSN Messenger : eti172@msn.com

