Ce cours est le premier d'une mini série dans laquelle nous étudierons les jeux en réseau multijoueur avec Godot Engine
Le jeu en réseau multijoueur est un défi excitant mais exigeant. Dans ce tutoriel, je vous propose de vous apprendre les notions qui vont vous permettre de développer un jeu multijoueur en réseau.
Le présent chapitre n'abordera l'implémentation mais va vous présenter quelques concepts essentiels concernant Godot et le réseau, concepts qui nous serons fort utile dans les chapitres suivants. C'est parti !
Principes généraux concernant le réseau
Qu'est-ce qu'un réseau
Un « réseau » est un maillage de périphériques (téléphones, ordinateurs, box wifi etc.) connectés entre eux. Autrement dit, deux périphériques ou plus reliés entre eux de façon à pouvoir échanger des informations forment un réseau. La connexion entre ces périphériques (qu'on peut aussi appeler "noeuds" peut être directe ou indirecte. Cela signifie que deux périphériques n'ont pas forcément besoin d'être reliés directement et physiquement entre eux pour être connectés.
Il suffit qu'un périphérique intermédiaire puisse faire le relai. Par conséquent, on schématise très souvent de manière simplifiée et abstraite un réseau en ne tenant compte que des connexions et non de la réalité physique qui lui est sous-jacente.
Notez que certains réseaux, comme Internet, sont publiques et d'autres (bien d'autres) sont privé. C'est par exemple le cas de la plupart des réseau domestiques (Wifi/ethernet à la maison) car la plupart des périphériques qui y sont connectés le sont grâce à un mot de passe et peuvent échanger des informations entre sans que les périphériques du reste du monde n'en sache rien.
Voyons maintenant les deux grands types de réseau.
Les réseaux décentralisés
La première des deux catégories est celle des réseau décentralisés (on parle aussi de réseau distribués, de P2P etc.) Dans cette catégorie les périphériques dialoguent entre eux sans intermédiaire, les messages circulent librement entre les membres du réseau (appelé pair) et le tout forme un ensemble joyeusement désorganisé.
Les réseaux centralisés
Le pendant de cette approche est le réseau centralisé où il existe un type de noeud particulier appelé le serveur. Dans ce type de réseau toutes les informations échangées affluent vers le serveur qui récupère, analyse et contrôle le flux de données pour éventuellement renvoyer des réponses vers les autres noeuds (appelés généralement des clients)Avantages et inconvénients des deux approches
Les réseau centralisés possède une caractéristique qui peut être un avantage comme un inconvénient : les pairs qui le constituent sont autonomes et peuvent échanger des informations librement sans dépendre d'une autorité extérieure (même si des solutions existent pour espionner ce genre de réseau comme celle qui sont mise en place par HADOPI par exemple).
Cela constitue un avantage quand on ne souhaite pas laisser de trace, et faire les choses simplement. Néanmoins, cette approche peut poser des difficultés si l'application a besoin de se référer à une autorité extérieure pour certains échanges (comme des échanges d'argent, des contrats etc.) L'avantage principal de l'approche centralisée est justement le fait qu'une autorité tierce (le serveur) intervienne dans les échanges afin d'offrir une traçabilité et un contrôle. C'est ce qui rend cette solution plus simple pour des projets générant des revenus ou simplement exigeant en matière de sécurité.
L'autre aspect intéressant des réseaux décentralisés est l'autonomie technologiques des pairs qui le constituent. En effet, l'absence de serveur force les pairs à gérer eux-mêmes leur ressources. Par conséquent, aucun coût n'est généré pour la maintenance, l'administration ou l'agrandissement d'un quelconque serveur, les pairs gèrent tout entre eux. Ceci rend réduit également le risque de panne généralisée du réseau : si quelques périphériques sont compromis, le réseau lui se maintient. Ce n'est pas le cas d'une infrastructure centralisée où une panne serveur aura des répercussions sur l'ensemble du réseau.
D'un autre côté, passer par un serveur permet aussi de garder le contrôle sur l'infrastructure qui gèrera les informations. La plupart des serveurs sont des machines à la fois bien plus puissantes et bien plus fiables que les machines des pairs standards et certains jeux, comme des MMORPG peuvent exiger ce genre d'infrastructure pour fonctionner correctement. Centraliser rend plus simple le fait de gérer de grande communautés d'utilisateur puisque
Comme vous pouvez le voir, il n'existe d'approche meilleure que l'autre dans l'absolu et tout dépendra du contexte et de l'objectif de chacune des applications.
Et dans la vraie vie, comment ça se passe ?
Les solutions réelles se situent souvent entre les deux extrêmes. De nombreuses approches consistent à combiner les deux, selon le sujet. Par exemple, un jeu peut décentraliser toute la gestion du gameplay mais centraliser les scores, les profils des joueurs, leur niveau d'expérience etc.
Notez tout de même que dans le jeu vidéo, la notion de client/serveur est, même dans une architecture très décentralisée, prédominante.
Et en ce qui concerne le jeu vidéo ?
Le jeu vidéo ne fait exception a la règle qu'on vient d'annoncer. Ainsi, les deux types d'approches coexistent. Les implémentations peuvent être diverses, néanmoins on peut remarquer quelques éléments intéressants.
Concernant les jeux en réseau à l'architecture plutôt centralisée :
- Le serveur est clairement séparé des périphériques des joueurs
- Le code du serveur occupe une place à part dans le projet (il peut même constituer un projet à part entière)
- Certains outils peuvent aider fortement l’implémentation d’un serveur (tel que Nakama)
Concernant les jeux en réseau à l'architecture plutôt décentralisée :
- Le serveur est l’un des périphériques des joueurs d’une partie
- Il existe donc un serveur par partie qui ne gère qu’un nombre limité de joueurs
- Le code du serveur est léger et n’est pas séparé du reste du projet
Comment faire du réseau avec Godot ?
Godot supporte nativement :- Les requêtes http (protocole TCP) : utilisée dans le web, elle peuvent aussi servir dans une jeu pour échanger des informations avec un serveur. Avantage : fiabilité, inconvénient : assez lentes et unidirectionnelles (le serveur ne prend jamais l'initiative d'envoyer des informations au client, il faut que ce-dernier le sollicite pour que le serveur réponde). On l'utilise en général pour les transactions, les sauvegardes et toutes les opérations ponctuelles.
- Les websockets (protocole TCP) : permet une liaison bidirectionnelle avec le serveur. Cela signifie que le serveur est en mesure de solliciter de lui-même les clients. Très utilisé dans les jeux en réseau au tour par tour
- Les socket UDP (protocole UDP) : le protocole UDP est, à l'inverse de TCP qui est fiable mais lent, peu fiable mais rapide. C'est ce type de protocole qui est utilisé dans les jeux "temps réel" dans lesquels une grande quantité d'information doit être échangée en peu de temps sans que l'information en elle-même soit tout le temps critique
- Le webrtc (protocole UDP) : permet de relier de manière décentralisée des pairs entre eux même si ils sont présents sur des réseau privés différents (nous y reviendrons)
Toutes ces technologies sont très intéressantes et nous permettront de faire plein de choses. Mais j'ai gardé le meilleur pour la fin:
À l'instar de Unity, Godot possède une API haut niveau pensée pour le jeu en réseau et directement présente dans l'arbre de scène (le SceneTree). Cette API est également intégrée au sein des langages de scripting lui-même (mots-clés en GDScript, annotations en C#). Elle possède en plus quelques caractéristiques intéressantes :
- Elle permet une gestion très décentralisée sans serveur global supportant toute la charge de travail
- Le code du serveur est confondu avec le reste du projet
- Le fonctionnement est basé sur la notion de procédure distante (RPC : Remote Procedure Call)
- La version la plus communément utilisée est basée sur le protocole UDP et il en existe aussi une utilisant les websockets et une autre le webrtc (nous y reviendrons)