Cette page n’est pas encore traduite : la version anglaise est affichée.
PlayServ SDK
Le backend de jeu livré avec le gameplay. PlayServ est un backend-as-a-service pour les jeux live : un studio fait tourner le backend de son jeu — données, joueurs, salles, matchmaking, commerce — sans en héberger un. Le SDK, c’est la façon dont votre code, côté serveur comme dans le moteur, travaille avec cette plateforme.
La simulation n’est pas votre code
Salles, collisions, déplacement, prédiction et synchronisation : tout cela tourne dans la plateforme. Votre jeu, ce sont des déclarations (entités, cartes, capacités, tables de butin, politique de synchronisation), des hooks (vos règles, appelées à des étapes nommées), des événements (on s’y abonne au lieu d’interroger en boucle) et des opérations (ce que vous demandez ou ordonnez). Chaque page de module s’organise exactement autour de ces quatre éléments.
Ce que vous n’avez pas à écrire est très concret : une boucle de jeu, l’assemblage des snapshots, un encodeur de deltas, la résolution des collisions, l’intégration du mouvement, la gestion des reconnexions, la validation des tirs avec compensation de latence. Un jeu comme Tanks tient en ~300 lignes. Premiers pas le construit pas à pas.
Modifier l’état déclaré, c’est déjà faire l’appel réseau
Il n’y a pas d’envoi. Vous déclarez comment un champ (field) se synchronise avec un seul attribut placé à côté de lui, et c’est la modification du champ qui constitue l’opération réseau. Les deltas par rapport au dernier état acquitté, la politique par aspect, la priorité et la fréquence d’envoi, la fenêtre de rétention et les hooks de changement découlent tous de cette déclaration ; vous n’en écrivez rien.
Il en va de même pour tout ce qui se déclare : un événement, un RPC, un groupe, un axe de classement (leaderboard). Une seule déclaration devient l’API typée dans chaque binding, un écran du panneau d’administration, des étapes nommées que vos hooks peuvent remplacer, des règles d’accès par acteur et du code généré pour chaque binding. C’est pourquoi vous versionnez la déclaration, pas le code généré. Voir Data & Subscriptions et Le schéma dans le code.
Les interfaces suivent l’acteur, pas le côté
Il n’y a ni SDK client ni SDK serveur. Un seul SDK est livré, et ce qu’un appel a le droit de faire dépend de l’acteur qui l’émet — un joueur, un service, un cerveau de bot, un opérateur.
Le cas pour lequel il est conçu : la machine d’un joueur qui crée une salle (room), puis la fait tourner. C’est un client maître (master-client), qui détient les interfaces de propriétaire de la salle et rien de plus. Un build room-visitor ne peut ni expulser ni fermer : ces interfaces sont absentes, pas désactivées.
Les droits se composent de permissions atomiques : il n’existe donc pas de niveaux de rôle prédéfinis, et un rôle filtre les données jusqu’à la ligne et à la colonne. Voir Qui prend les décisions, et Access & Roles pour la façon d’écrire des droits accordés (grant).
Une seule conception, une seule pile
Comment il s’écrit
Le SDK est une seule conception, avec deux façons de la spécialiser, et rien ne descend d’un niveau tant que le niveau supérieur peut l’exprimer. Les principes communs sont identiques dans chaque binding. La forme propre à un langage ne reprend que ce que son paradigme ne peut pas exprimer de la manière commune. La forme propre à un moteur ne reprend que ce qu’un moteur remodèle par-dessus son langage — dans Unreal, une déclaration se loge dans la macro de réflexion du moteur lui-même.
Comment il s’exécute
Votre code de jeu s’adresse aux modules, et à rien d’autre. Les modules sont assemblés à partir de quatre primitives : événements, RPC, données et abonnements, groupes. En dessous se trouve le hub, que vous n’appelez jamais : injection de dépendances, montage des modules, session, restauration de l’état, qualité de service des messages. Plus bas encore, les adaptateurs de transport, un par protocole ; lequel transporte un appel, votre code ne le décide pas et ne s’en aperçoit pas.
Les deux moitiés en détail : Comment le SDK est construit, jusqu’à Sous le capot.
Les modules se composent, rien n’hérite
Pas de module de base dont dériver, pas de hiérarchie à étendre : les modules forment un graphe, parce que les vraies fonctionnalités traversent les branches. Le matchmaking réserve des places (seat) dans les salles, le butin dépose des objets par l’intermédiaire de la carte, un chat vit à l’intérieur d’une salle.
Ici, « héritage » recouvre quatre mécanismes différents, qu’il vaut la peine de distinguer : les RPC d’une entité font partie de l’entité ; un preset est un ensemble nommé d’aspects, pas une classe de base ; surcharger une étape de la plateforme revient à poser un attribut sur votre remplacement ; un module en emprunte un autre via un décorateur qui restreint l’interface empruntée. Voir Héritage et composition.
Qui voit quoi : c’est déclaré, pas filtré côté client
À quarante joueurs, un snapshot de toute la salle passe très bien ; à deux cents, non. Les règles de zone d’intérêt (interest rules) décident qui reçoit quelle tranche. Paquet par acteur et diffusion (broadcast) sont deux modes de livraison d’un même modèle déclaré : passer de l’un à l’autre relève de la configuration, pas d’une réécriture. Les objets lointains passent par des niveaux de détail (detail tier) déclarés avant de disparaître.
C’est aussi une propriété de sécurité : l’état qui ne doit pas fuiter n’est jamais envoyé. Le brouillard de guerre et les champs réservés au propriétaire sont absents du paquet, pas masqués côté client. Spectateurs, administrateurs et replays obtiennent une vue plus large parce qu’ils détiennent des droits accordés plus larges. Voir Visibility.
Ce qui survit à la perte d’un hôte
La mort d’un hôte ne met pas fin au match. Pendant la partie, l’état de la salle n’est pas copié d’un hôte à l’autre : un propriétaire unique garantit l’ordre des opérations sans recourir au consensus. Le match survit parce que son état est déclaré, et l’état déclaré est conservé hors de l’hôte, sous forme de snapshots pris à un intervalle déclaré. Un hôte de remplacement reprend à partir du dernier snapshot.
Le remplaçant dispose de tout l’état tel qu’il était au moment de ce snapshot : ce qui s’est joué depuis est perdu. Un déploiement utilise le même mécanisme, sans la perte : retirer un hôte (drain), c’est déclencher volontairement le basculement.
L’état propre au moteur n’est pas restauré
L’état que vous gardez uniquement dans des acteurs du moteur n’est pas déclaré : un hôte de remplacement ne l’a donc pas. ::: Voir Ce qui survit à la perte d’un hôte, et Rooms pour le délai de grâce (grace window) pendant lequel un joueur peut revenir.
N’importe quelle étape de la plateforme peut devenir la vôtre
Chaque scénario de la plateforme est une chaîne de fonctions enregistrées, dont vous remplacez ou enveloppez un maillon. Connexion, validation d’entrée, achat, soumission, envoi de fichier : chacun est une étape nommée. Votre remplacement se déclare avec un attribut, les versions sont choisies selon une condition, et l’étape d’origine de la plateforme sert de repli.
Au lieu de forker le code de la plateforme, vous remplacez ses étapes. Voir Extensibility.
Une interface, six langages
Un contrat, six projections : C#, TypeScript, Python et Go côté serveur ; Unreal C++ et Unity C# générés dans le moteur. Chaque exemple de code de ce site montre les six, et quand un binding n’offre pas d’interface pour une étape, l’onglet explique pourquoi : l’étape s’exécute hors du moteur, ou c’est un autre acteur qui détient le droit de faire cet appel.
Deux conséquences à connaître avant de choisir un langage. Les RPC prennent des objets SDK par référence plutôt que des DTO aplatis. Et les primitives asynchrones sont intégrées — canaux, flux (stream) et adressage de groupe : vous pouvez parler à tout un groupe et recueillir les réponses, ou consommer un fichier morceau par morceau pendant qu’il est encore en cours d’envoi.
Il existe aussi un hôte déterministe en mémoire, qui exécute votre code de jeu sans backend derrière lui, avec un temps que vous contrôlez : vos tests sont donc déterministes. Voir Threads, cycle de vie et tests.
Ce qui n’est délibérément pas dans le SDK — déploiements, facturation, administration de l’organisation et des utilisateurs — se trouve sur le plan opérateur. La barre latérale cartographie tout le reste ; Premiers pas est le chemin le plus court pour commencer.