Plongée profonde dans le backend du jeu - Overwatch

Plongée approfondie dans la conception du jeu multijoueur et l'architecture du netcode d'Overwatch (2016) par Tim Ford.

Points Clés

Points Clés

Points Clés

  • ECS en tant qu'Activateur de Netcode : Overwatch a réduit la surface du netcode de tout le gameplay à seulement trois systèmes sur des centaines, rendant un problème intrinsèquement complexe gérable.

  • Cadres de Commande et Tickrate Adaptatif : La simulation fonctionne sur des cadres de commande fixes de 16 ms (passant à 7 ms en mode tournoi) — un compromis délibéré entre réactivité et coût serveur que tout studio multijoueur devrait comprendre.

  • Le Rollback Nécessite un Serveur Digne de Confiance : Le système de réconciliation de Overwatch fonctionne car un serveur dédié et autoritaire détient la vérité objective. Sans cela, l'ensemble du modèle de rollback et de replay ne peut tout simplement pas exister.

  • Dilatation du Temps comme Bouclier contre la Perte de Paquets : Lorsque le serveur détecte une pénurie d'entrées, il indique au client de simuler légèrement plus vite, inondant le tampon d'entrées avant que la perte ne puisse causer des erreurs de prédiction. Cette boucle de rétroaction fonctionne constamment, invisiblement.

  • Prédire Tout, Y Compris les Fusées : Overwatch prédit toutes les capacités et projectiles par défaut, optant pour une désactivation uniquement lorsque cela est nécessaire ; une approche inhabituelle en 2017 qui rendait le jeu considérablement plus réactif.

Tim Ford, maintenant Directeur du studio chez Kintsugiyama et précédemment Programmeur Principal Gameplay sur Overwatch depuis la création du jeu à l'été 2013, a présenté l'architecture de gameplay et le netcode de Overwatch à la GDC 2017. La conférence couvre comment Blizzard a construit un système multijoueur autoritaire sur le serveur, lourd en prédictions, basé sur une architecture stricte de type Entity Component System, et pourquoi ce choix architectural s'est avéré inséparable du succès du netcode.

Indirectement, cela met en lumière les meilleures pratiques que tout studio de jeu, grand ou petit, peut ajouter à son Multiplay pour améliorer son architecture en ligne. Jetons un coup d'œil à l'intérieur.

Qu'est-ce que l'ECS et pourquoi est-il important pour le Netcode ?

L'architecture Entity Component System sépare un monde de jeu en trois concepts distincts. Les entités ne sont que des identifiants ; rien d'autre. Les composants sont des conteneurs de données purs attachés aux entités; ils stockent l'état du jeu et ne possèdent aucun comportement. Les systèmes contiennent toute la logique et s'exécutent contre toute entité qui a la combinaison spécifique de composants dont le système se préoccupe.

Cette séparation stricte oblige chaque comportement à exister dans un espace clairement défini et isolé. Comme l'a dit Ford, l'objectif est un « gouffre de succès », c'est-à-dire une architecture si contraignante que vous êtes poussé à écrire un code cohérent, maintenable et découplé presque par défaut. Dans la base de code de production d'Overwatch, avec environ 46 systèmes côté client et 103 types de composants, seuls trois systèmes sont responsables du netcode de gameplay : mouvement, arme et script d'état. Le reste du moteur ne l'affecte pas. Cet isolement est ce qui rend le netcode maintenable à mesure que le roster de héros grandit.

À noter : ECS est un modèle qui mérite d'être exploré en profondeur par lui-même. Nous pourrions l'aborder dans un article dédié, car ses implications s'étendent bien au-delà du netcode.

Command Frames, Fréquence de Ticks et le Coût de la Réactivité

La simulation d'Overwatch fonctionne sur des frames de commande fixes de 16 millisecondes chacune, environ 60Hz. En configuration de tournoi, cela tombe à 7ms, plus proche de 128Hz. À chaque frame, le client consomme les entrées des joueurs aussi près que possible du moment présent et les envoie au serveur. L'horloge du client est toujours en avance sur celle du serveur de la moitié du temps aller-retour plus un frame de commande en tampon. À 160ms RTT, c'est environ 96ms d'avance.

Cela est important pour le coût. Un taux de ticks plus élevé (c'est-à-dire des frames de commande plus courtes) nécessite plus de cycles CPU serveur par seconde et plus de bande passante réseau par match. Passer de 16 ms à 7 ms en mode tournoi n'est pas gratuit. C'est un choix délibéré réservé au jeu compétitif, où l'amélioration marginale de la réactivité justifie les dépenses supplémentaires d'infrastructure. Pour la matchmaking générale, 16 ms trouve le bon équilibre.

Ce coût supplémentaire s'échelonne linéairement avec le taux de ticks. Une infrastructure qui déploie des serveurs au plus proche des joueurs aide à maintenir une faible latence sans avoir besoin de compenser uniquement par des augmentations du taux de ticks. La plateforme d'orchestration de serveurs de jeux d'Edgegap réduit la latence moyenne de 58% en plaçant les serveurs au bord du réseau le plus proche de chaque population de joueurs.

Le Rollback ne Fonctionne Réellement qu'avec un Serveur Dédié

« Ceci est le problème le plus important du netcode pour les ingénieurs de gameplay que nous devions résoudre », comme l'a décrit Ford. L'objectif est un jeu d'action en réseau réactif, ce qui signifie la prédiction des actions des joueurs localement. Mais nous ne pouvons pas faire confiance au client pour l'autorité de simulation, car, comme l'a noté Ford, « certains clients sont malveillants ». Comme souligné dans nos articles, l'architecture de réseau peer-to-peer est un refuge pour les tricheurs qui peuvent manipuler les serveurs de jeu hébergés par les joueurs, et même les relays présentent des risques de sécurité.

La solution est un serveur dédié, autoritaire et digne de confiance.

Lorsqu'un client prédit de manière incorrecte, par exemple, il pensait que le joueur courait, mais le serveur a déterminé qu'il était étourdi, le client revient à l'instantané de mouvement autoritaire du serveur et rejoue chaque entrée en tampon jusqu'au moment présent. Parce que la simulation de mouvement de personnage est hautement déterministe, cette relecture reproduit de manière fiable l'état correct. La correction est fluide et, dans la grande majorité des cas, invisible.

Ce système ne peut tout simplement pas exister dans une architecture basée sur le peer-to-peer ou sur relay. Il n'y a pas de vérité fondamentale à laquelle revenir. Le serveur de jeu dédié fonctionnant dans le cloud n'est pas juste une commodité; c'est le prérequis structurel pour l'ensemble du modèle de prédiction et de réconciliation. Sans cela, vous devez choisir entre faire confiance aux clients ou faire attendre chaque joueur pour la confirmation du serveur avant de voir une réponse à leur entrée.

Pour plus d'informations sur le rollback, assurez-vous de lire notre article sur le netcode à rollback ici, ainsi que des idées sur la façon de réduire la latence où nous comparons le netcode à rollback par rapport au délai d'entrée.

Dilatation du Temps : Combattre la Perte de Paquets Proactivement

Lorsque des paquets sont perdus et que le serveur manque d'entrées à simuler, il duplique la dernière entrée connue du joueur et espère le meilleur. Cela crée des prédictions erronées. La solution d'Overwatch n'est pas d'absorber les dégâts; c'est de les prévenir.

Lorsque le serveur détecte une famine d'entrées, il notifie le client, qui commence à dilater le temps. Au lieu d'un pas de temps fixe de 16 ms, le client le traite comme environ 15,2 ms, simulant un peu plus rapidement et versant plus d'entrées dans le tuyau réseau pour constituer un tampon du côté serveur. Une fois les conditions stabilisées, le client dilate à nouveau dans l'autre direction, drainant progressivement ce tampon. Cette boucle de rétroaction fonctionne constamment.

Associée à cela, il y a une technique que Ford remonte à Quake World : une fenêtre coulissante d'entrées. Plutôt que d'envoyer uniquement l'entrée du cadre actuel, le client regroupe chaque entrée depuis le dernier état de mouvement reconnu par le serveur dans un seul paquet. Parce que les joueurs maintiennent généralement les touches plutôt que de les tapoter à 60Hz, cela se compresse très efficacement. Si un paquet est perdu, le suivant transporte toujours toutes les entrées manquantes, comblant les trous avant que la simulation ne s'exécute. Deux systèmes complémentaires. Aucun n'est novateur seul, mais ensemble, ils rendent la perte de paquets largement invisible pour le joueur.

Prédire Tout, Même les Rockets

La plupart des jeux multijoueurs prédisent le mouvement des joueurs et s'arrêtent là. Overwatch prédit tout (c'est-à-dire, mouvement, toutes les capacités et les armes) par défaut. Les équipes doivent explicitement opter pour la non-prédiction d'une capacité spécifique. Cette philosophie s'étend aux grands projectiles visibles comme les roquettes de Pharah.

À l'époque, les conférences GDC de studios respectés par Blizzard déconseillaient explicitement de le faire. Les roquettes sont de grands objets physiques dans le monde, et non des traceurs, et une prédiction erronée les fait disparaître visuellement. Blizzard a trouvé un moyen de le faire quand même. « Prédire les roquettes, c'est cool », comme Ford l'a dit. « Ça décoiffe vraiment. » Parfois, une roquette disparaît. Il y a le rare post sur le forum. Ça en vaut largement la peine.

La leçon pour tout développeur de tireur : partir sur une prédiction par défaut. Se retirer sélectivement. Les gains en réactivité sont réels, et les joueurs les ressentent même s'ils ne peuvent pas articuler pourquoi.

Enregistrement des Impacts : Ajuster Uniquement ce dont Vous Avez Besoin

Lorsqu'un joueur tire, le serveur remonte le monde à la trame de référence du tireur avant de calculer si le tir a touché. Cette réconciliation en arrière est une technique bien établie. Ce qui est moins courant, c'est comment Overwatch gère son coût.

Plutôt que de remonter chaque entité dans la scène, un volume de délimitation spatial représentant environ la dernière demi-seconde de mouvement de chaque entité est vérifié par rapport au rayon de la balle en premier. Seules les entités dont le volume de délimitation s'intersecte sont entièrement remontées pour une calcul précis des impacts. Cela élimine la grande majorité des candidats avant que tout calcul coûteux ne soit effectué.

Au-delà d'environ 220ms de temps aller-retour, la prédiction d'impact est totalement désactivée. Le système passe à l'extrapolation (par exemple, prévoir la position de la cible en fonction de la dernière trajectoire connue) plutôt que de remonter une cible si loin en arrière qu'une victime qui a efficacement esquivé derrière un abri pourrait encore mourir. C'est une contrainte d'équité délibérée.

Déférer : Un Effet Secondaire, Un Site d'Appel

Overwatch diffère les grands effets secondaires plutôt que de les invoquer là où ils sont nécessaires. Le principe est simple : lorsqu'un comportement déclenche un gros travail, demandez-vous si ce travail doit se dérouler immédiatement. Generalement, ce n’est pas le cas.

L'exemple le plus clair est les effets d'impact. Plusieurs systèmes à travers le moteur doivent faire apparaître des impacts de surface, des balles hitscan aux projectiles explosifs en passant par les armes à rayons. Chaque création touche la durée de vie de l'entité, la gestion de la scène et la gestion des ressources. Plutôt que de disperser cette logique à travers une douzaine de sites d'appel, Overwatch met en file d'attente des enregistrements de contact en attente dans un composant singleton. Une fois par cadre, avant la préparation du rendu, un système unique traite l'ensemble du lot.

Comme Ford a résumé la leçon : « Les comportements sont beaucoup moins complexes s'ils sont exprimés en un seul site d'appel où tous les grands effets secondaires comportementaux sont localisés à ce site d'appel. » Les avantages s'empilent au-delà de la clarté. Meilleure localité de cache, possibilité d'imposer une limite budgétaire par trame à la création d'effets, et capacité à lisser les pointes lorsque de nombreux effets sont demandés simultanément.

Informations Supplémentaires pour les Développeurs de Jeux Multijoueurs

  • L'accès explicite aux composants permet le multi-threading. Si les systèmes déclarent à l'avance quels composants ils lisent par rapport à ceux qu'ils écrivent, le planificateur peut exécuter en parallèle les systèmes non conflictuels en toute sécurité. Ford a noté rétrospectivement que l'approche ad hoc d'Overwatch obscurcissait cette opportunité. Faire respecter des définitions de tuples strictes dès le début aurait révélé la complexité plus tôt et facilité le parallélisme sécurisé.

  • L'horloge de simulation doit être fixe, même si le moteur de rendu ne l'est pas. La simulation d'Overwatch fonctionne à 60Hz obligatoire. Si le moteur de rendu tombe à 30fps, le moteur exécute deux ticks de simulation pendant ce cadre. La simulation est bien moins coûteuse que le rendu, donc c'est gérable, mais le taux de simulation fixe est non négociable pour le déterminisme. Et si le serveur ne peut pas suivre, Ford a alerté qu'il entre dans « une spirale de la mort » — chaque cadre en retard forçant plus de ticks, se multipliant jusqu'à ce que le serveur s'effondre complètement. L'optimisation n'est pas optionnelle.

  • Les règles d'architecture prennent du temps à découvrir. Il a fallu environ un an et demi à l'équipe d'Overwatch pour se fixer sur leurs règles ECS. Le code qui précédait ou viol

Écrit par

l'équipe Edgegap

Intégrer Edgegap facilement en quelques minutes

Commencez l'intégration maintenant!

Commencez l'intégration maintenant!

Intégrer Edgegap facilement en quelques minutes