CRÉEZ VOTRE MONDE
Joueurs et Personnages : Basiq...
ZEPETO Players
22 min
zepetoplayers est une classe manager (singleton) conçue pour contrôler à la fois le joueur zepeto et le personnage zepeto en ajoutant zepetoplayers à une scène, vous pouvez créer, supprimer et manipuler un joueur zepeto zepetoplayer représente une instance individuelle d'un personnage zepeto utilisée pour gérer à la fois le joueur que vous contrôlez directement dans un monde multijoueur et d'autres joueurs chaque zepetoplayer créé dans un monde multijoueur se voit attribuer un id de session unique et est géré à l'aide de cet id de session parce que zepetoplayer possède les attributs de zepetocharacter, il peut être contrôlé à l'aide de fonctions liées à zepetocharacter il existe trois types de zepetoplayer zepetoplayer description joueur local représente une instance de personnage zepeto directement contrôlée par l'utilisateur local \ équipé des composants character controller/zepeto camera joueur réseau (joueur distant) une instance de personnage zepeto qui peut être chargée et utilisée dans du contenu multijoueur \ n'a pas les composants character controller/zepeto camera attachés joueur bot une instance de personnage zepeto pour du contenu multijoueur, mais contrôlée par un bot au lieu d'un utilisateur réel utilisé comme substitut lors du démarrage d'un monde multijoueur avec un nombre insuffisant de joueurs ou si un joueur quitte pendant le jeu \ n'a pas les composants character controller/zepeto camera attachés veuillez vous référer au guide suivant \[ zepeto player docid\ cshsh6drio eccnexl59u ] \[ guide de création de joueurs bot docid tsl6iaqb7ph9pidbenkm ] zepetocharacter est une unité d'instance de base du personnage zepeto qui peut être chargée et contrôlée dans la scène du monde zepetocharacter possède l'apparence d'un avatar créé via l'application zepeto veuillez vous référer au guide suivant \[ personnage zepeto docid\ xn7rosmexsdz7kgw7d5rt ] ajouter des zepetoplayers dans la fenêtre hiérarchie, sélectionnez zepeto → onglet zepetoplayers vous pouvez maintenant l'ajouter à votre scène notez que l'ajout de zepetoplayers ne fait pas entrer le zepeto player dans la scène vous devez implémenter un script en utilisant l'api de création de personnage de zepetoplayers si vous souhaitez créer rapidement et essayer uniquement le local player dans une scène, référez vous au guide veuillez vous référer au guide suivant \[ créer un personnage zepeto docid\ geffw2qsrck7y989 y9of ] pour un exemple sur la façon d'afficher le nom et la photo de profil d'un joueur zepeto, consultez le guide veuillez vous référer au guide suivant \[ informations utilisateur docid\ gkpnghpf f f d2pwkbak ] api des joueurs zepeto si vous êtes intéressé par l'api zepetoplayers, consultez la documentation veuillez vous référer au guide suivant \[ api zepeto character controller ] ce guide couvre principalement des exemples d'utilisation des joueurs zepeto dans des scénarios multijoueurs implémentation de la synchronisation de position multijoueur utilisant les joueurs zepeto dans un monde un joueur, seul un joueur local doit être créé et puisque seul le joueur local apparaît à l'écran, la synchronisation n'est pas nécessaire cependant, dans un monde multijoueur, non seulement le joueur local que vous contrôlez directement mais aussi d'autres joueurs, appelés joueurs réseau, doivent être affichés à l'écran chaque action des joueurs réseau se déplacer, sauter et effectuer des gestes spécifiques doit apparaître de manière identique sur votre écran ce processus est appelé synchronisation sans mettre en œuvre le script de synchronisation, vous ne pourrez pas voir l'apparence ou le mouvement du joueur réseau dans un monde multijoueur sans synchronisation, le seul moyen de savoir si un autre client est entré dans la salle est par le bouton d'accueil étape 1 configuration de l'environnement multijoueur il est recommandé de commencer par comprendre les paramètres de base et les concepts du multijoueur à travers une vidéo tutorielle multijoueur veuillez vous référer au guide suivant \[ tutoriel multijoueur docid\ vf1p1ejmzrhgtbakllyb9 ] \[ multiplay docid\ qoqco4ojnwlll4um8zmzd ] étape 2 affichage des autres joueurs sur votre écran votre joueur local est traité comme un joueur réseau sur l'appareil de quelqu'un d'autre cela signifie que même votre joueur local doit envoyer des informations au serveur pour la synchronisation tous les joueurs connectés au monde multijoueur doivent partager leurs informations tous les clients connectés à la salle multijoueur partagent les données d'état de la salle multijoueur ces données d'état de la salle suivent le schéma défini dans schemas json (veuillez considérer le schéma comme une structure de données) dans ce guide, vous synchroniserez la position du joueur à travers les données de l'état de la salle ainsi, définissez un schéma dans schemas json qui peut représenter les données de position pour chaque joueur schema json { "state" {"players" {"map" "player"}}, "player" {"sessionid" "string","zepetouserid" "string","transform" "transform","state" "number","substate" "number"}, "transform" {"position" "vector3","rotation" "vector3"}, "vector3" {"x" "number","y" "number","z" "number"} } veuillez vous référer au guide suivant \[ état de la salle multijoueur docid 7uk44f1 oflhkar8sauy ] 👍 conseils stockez toutes les informations que les serveurs et tous les clients doivent partager dans le état de la salle multiplay enregistrez les données individuelles pour chaque joueur, telles que les niveaux, les points d'expérience, les scores, etc , en utilisant datastorage le script du serveur peut reconnaître quand un autre joueur est entré dans la salle et peut envoyer cette information au client pour charger ce joueur dans la scène étape 2 1 script de serveur de base lorsque un joueur entre dans la salle du monde multijoueur, onjoin() est appelé dans le script du serveur, ajoutez les informations du joueur connecté à l'état de la salle des joueurs de plus, lorsque un joueur quitte la salle, onleave() est appelé le script du serveur supprimera les informations du joueur qui a quitté l'état des joueurs de la salle import {sandbox, sandboxoptions, sandboxplayer} from "zepeto multiplay"; import {player} from "zepeto multiplay schema"; export default class extends sandbox { oncreate(options sandboxoptions) { } async onjoin(client sandboxplayer) { const player = new player(); player sessionid = client sessionid; if (client userid) { player zepetouserid = client userid; } // gérer l'objet player en utilisant sessionid, une valeur clé unique de l'objet client // le client peut vérifier les informations sur l'objet joueur ajouté en ajoutant l'événement add onadd à l'objet joueurs this state players set(client sessionid, player); } async onleave(client sandboxplayer, consented? boolean) { this state players delete(client sessionid); } } étape 2 2 script client de base lors de la création d'un monde multiplay, un script client est nécessaire pour communiquer avec le serveur ci dessous un exemple d'un script client fondamental pour le jeu multijoueur du côté client, nous gérons les données du joueur à afficher dans notre client en utilisant la currentplayers structure de données de carte la ligne de code pivot est illustrée ci dessous zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, spawninfo, islocal); lorsque le client reçoit des informations sur le joueur de l'état de la salle du serveur et qu'un nouveau joueur rejoint la salle, un id de session est attribué si l'id de session du joueur en cours de création correspond à notre propre id de session, le joueur est considéré comme local dans ce cas, le joueur sera instancié avec islocal = true , indiquant qu'il s'agit du joueur local par la suite, les joueurs qui ne sont pas locaux sont créés avec islocal = false cela garantit que les apparences de tous les joueurs, locaux et non locaux, sont affichées à l'écran import {zepetoscriptbehaviour} from 'zepeto script' import {zepetoworldmultiplay} from 'zepeto world' import {room, roomdata} from 'zepeto multiplay' import {player, state, vector3} from 'zepeto multiplay schema' import {characterstate, spawninfo, zepetoplayers, zepetoplayer, characterjumpstate} from 'zepeto character controller' import as unityengine from "unityengine"; export default class multiplayclientcode extends zepetoscriptbehaviour { public multiplay zepetoworldmultiplay; private room room; private currentplayers map\<string, player> = new map\<string, player>(); private zepetoplayer zepetoplayer; private start() { this multiplay roomcreated += (room room) => { this room = room; }; this multiplay roomjoined += (room room) => { room onstatechange += this onstatechange; }; } private onstatechange(state state, isfirst boolean) { // lorsque le premier événement onstatechange est reçu, un instantané complet de l'état est enregistré if (isfirst) { // \[charactercontroller] (local) appelé lorsque l'instance du joueur est complètement chargée dans la scène zepetoplayers instance onaddedlocalplayer addlistener(() => { const myplayer = zepetoplayers instance localplayer zepetoplayer; this zepetoplayer = myplayer; }); // \[charactercontroller] (local) appelé lorsque l'instance du joueur est complètement chargée dans la scène zepetoplayers instance onaddedplayer addlistener((sessionid string) => { const islocal = this room sessionid === sessionid; if (!islocal) { const player player = this currentplayers get(sessionid); } }); } let join = new map\<string, player>(); let leave = new map\<string, player>(this currentplayers); state players foreach((sessionid string, player player) => { if (!this currentplayers has(sessionid)) { join set(sessionid, player); } leave delete(sessionid); }); // \[roomstate] créer une instance de joueur pour les joueurs qui entrent dans la salle join foreach((player player, sessionid string) => this onjoinplayer(sessionid, player)); // \[roomstate] supprimer l'instance de joueur pour les joueurs qui quittent la salle leave foreach((player player, sessionid string) => this onleaveplayer(sessionid, player)); } private onjoinplayer(sessionid string, player player) { console log(`\[onjoinplayer] joueurs sessionid ${sessionid}`); this currentplayers set(sessionid, player); // créer le joueur const islocal = this room sessionid === player sessionid; zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, new spawninfo(), islocal); } private onleaveplayer(sessionid string, player player) { console log(`\[onremove] joueurs sessionid ${sessionid}`); this currentplayers delete(sessionid); zepetoplayers instance removeplayer(sessionid); } } maintenant, lorsque un joueur entre, vous pouvez confirmer que le personnage zepeto est créé sur votre écran mais, le mouvement du joueur n'est pas encore reflété à l'écran passons maintenant à la synchronisation de la position étape 3 synchronisation en récupérant les informations des autres joueurs pour la synchronisation, chaque fois qu'un joueur se déplace ou effectue une action, il doit envoyer son changement de statut au serveur envoyer un message contenant leur changement de statut au serveur se fait par le biais de la communication par message de salle lorsque le serveur reçoit un message concernant un changement de statut d'un joueur, il met à jour l'état de la salle veuillez vous référer au guide suivant \[ message de la salle multiplay docid\ m0wk142xsx834bmxmuem9 ] par exemple, considérons que votre joueur local s'appelle b lorsqu'un joueur réseau a rejoint la salle, il est instancié aux coordonnées x 0, y 0, z 0 si le joueur a se déplace vers la position x 10, y 0, z 0, b n'a aucun moyen réel de savoir qu'a se déplace c'est parce que les deux sont opérés localement sur des appareils séparés, donc sur des clients séparés ainsi, la personne contrôlant a doit communiquer son mouvement au serveur via un message de salle une fois que le serveur reçoit cette information, il informe tous les présents dans la salle de la position en temps réel d'a de cette façon, b est enfin conscient qu'a se déplace pour que le serveur notifie les autres joueurs, il existe deux méthodes utiliser la diffusion de message de salle mettre à jour l'état de la salle, puis faire en sorte que les clients récupèrent et appliquent l'état de la salle ce guide utilise la deuxième méthode de mise à jour de l'état de la salle étant donné qu'un joueur zepeto chargé dans la scène possède des attributs de personnage zepeto, vous pouvez utiliser les fonctions de personnage zepeto pour commander des mouvements vers des emplacements spécifiques ou initier des sauts pour que le client de b puisse visualiser le mouvement de a vers x 10, y 0, z 0, l'approche la plus intuitive est d'utiliser movetoposition() cette fonction déplacera le joueur vers la position la plus récente de a telle que reçue du serveur non seulement les changements de position, mais aussi les gestes, l'utilisation de compétences, la collecte d'objets et tous les changements d'état nécessitent une communication serveur client pour la synchronisation vous devrez mettre en œuvre la synchronisation pour garder chaque action en harmonie à travers le réseau 👍 résumé du concept de synchronisation lorsqu'un joueur local a un changement de statut, il l'envoie au serveur en utilisant room message le serveur notifie tous les autres joueurs sauf le joueur local au sujet du changement de statut lors de la réception du message de changement de statut, le code client met à jour le statut du joueur qui a envoyé le message étape 3 1 script serveur avec synchronisation de position complète dans le script serveur de base, une implémentation supplémentaire est nécessaire pour mettre à jour l'état de la salle chaque fois qu'un message concernant un changement de statut est reçu du client du joueur local import {sandbox, sandboxoptions, sandboxplayer} from "zepeto multiplay"; import {player, transform, vector3} from "zepeto multiplay schema"; export default class extends sandbox { constructor() { super(); } oncreate(options sandboxoptions) { // appelé lorsque l'objet room est créé // gérer l'initialisation de l'état ou des données de l'objet room this onmessage("onchangedtransform", (client, message) => { const player = this state players get(client sessionid); const transform = new transform(); transform position = new vector3(); transform position x = message position x; transform position y = message position y; transform position z = message position z; transform rotation = new vector3(); transform rotation x = message rotation x; transform rotation y = message rotation y; transform rotation z = message rotation z; if (player) { player transform = transform; } }); this onmessage("onchangedstate", (client, message) => { const player = this state players get(client sessionid); if (player) { player state = message state; player substate = message substate; // contrôleur de personnage v2 } }); } async onjoin(client sandboxplayer) { // créer l'objet joueur défini dans schemas json et définir la valeur initiale console log(`\[onjoin] sessionid ${client sessionid}, userid ${client userid}`) const player = new player(); player sessionid = client sessionid; if (client userid) { player zepetouserid = client userid; } // gérer l'objet player en utilisant sessionid, une valeur clé unique de l'objet client // le client peut vérifier les informations sur l'objet joueur ajouté en ajoutant l'événement add onadd à l'objet players this state players set(client sessionid, player); } async onleave(client sandboxplayer, consented? boolean) { // en définissant allowreconnection, il est possible de maintenir la connexion pour le circuit, mais de nettoyer immédiatement dans le guide de base // le client peut vérifier les informations sur l'objet joueur supprimé en ajoutant l'événement add onremove à l'objet players this state players delete(client sessionid); } } étape 3 2 script client avec synchronisation de position complète les implémentations clés dans le script client de base sont appeler automatiquement onstatechange lorsque l'état de la salle du serveur change en utilisant le sendmessageloop(0 04) fonction, envoyez la position du joueur local et les informations sur l'état de saut du personnage au serveur toutes les 0,04 secondes import {zepetoscriptbehaviour} from 'zepeto script' import {zepetoworldmultiplay} from 'zepeto world' import {room, roomdata} from 'zepeto multiplay' import {player, state, vector3} from 'zepeto multiplay schema' import {characterstate, spawninfo, zepetoplayers, zepetoplayer, characterjumpstate} from 'zepeto character controller' import as unityengine from "unityengine"; export default class clientstarterv2 extends zepetoscriptbehaviour { public multiplay zepetoworldmultiplay; private room room; private currentplayers map\<string, player> = new map\<string, player>(); private zepetoplayer zepetoplayer; private start() { this multiplay roomcreated += (room room) => { this room = room; }; this multiplay roomjoined += (room room) => { room onstatechange += this onstatechange; }; this startcoroutine(this sendmessageloop(0 04)); } // envoyer la transformation du personnage local au serveur à l'intervalle prévu private sendmessageloop(tick number) { while (true) { yield new unityengine waitforseconds(tick); if (this room != null && this room isconnected) { const hasplayer = zepetoplayers instance hasplayer(this room sessionid); if (hasplayer) { const character = zepetoplayers instance getplayer(this room sessionid) character; this sendtransform(character transform); this sendstate(character currentstate); } } } } private onstatechange(state state, isfirst boolean) { // lorsque le premier événement onstatechange est reçu, un instantané complet de l'état est enregistré if (isfirst) { // \[charactercontroller] (local) appelé lorsque l'instance du joueur est entièrement chargée dans la scène zepetoplayers instance onaddedlocalplayer addlistener(() => { const myplayer = zepetoplayers instance localplayer zepetoplayer; this zepetoplayer = myplayer; }); // \[charactercontroller] (local) appelé lorsque l'instance du joueur est entièrement chargée dans la scène zepetoplayers instance onaddedplayer addlistener((sessionid string) => { const islocal = this room sessionid === sessionid; if (!islocal) { const player player = this currentplayers get(sessionid); // \[roomstate] appelé chaque fois que l'état de l'instance du joueur est mis à jour player onchange += (changevalues) => this onupdateplayer(sessionid, player); } }); } let join = new map\<string, player>(); let leave = new map\<string, player>(this currentplayers); state players foreach((sessionid string, player player) => { if (!this currentplayers has(sessionid)) { join set(sessionid, player); } leave delete(sessionid); }); // \[roomstate] créer une instance de joueur pour les joueurs qui entrent dans la salle join foreach((player player, sessionid string) => this onjoinplayer(sessionid, player)); // \[roomstate] supprimer l'instance de joueur pour les joueurs qui quittent la salle leave foreach((player player, sessionid string) => this onleaveplayer(sessionid, player)); } private onjoinplayer(sessionid string, player player) { console log(`\[onjoinplayer] joueurs sessionid ${sessionid}`); this currentplayers set(sessionid, player); const spawninfo = new spawninfo(); const position = this parsevector3(player transform position); const rotation = this parsevector3(player transform rotation); spawninfo position = position; spawninfo rotation = unityengine quaternion euler(rotation); const islocal = this room sessionid === player sessionid; zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, spawninfo, islocal); } private onleaveplayer(sessionid string, player player) { console log(`\[onremove] joueurs sessionid ${sessionid}`); this currentplayers delete(sessionid); zepetoplayers instance removeplayer(sessionid); } private onupdateplayer(sessionid string, player player) { const position = this parsevector3(player transform position); const zepetoplayer = zepetoplayers instance getplayer(sessionid); var movedir = unityengine vector3 op subtraction(position, zepetoplayer character transform position); movedir = new unityengine vector3(movedir x, 0, movedir z); if (movedir magnitude < 0 05) { if (player state === characterstate moveturn) return; zepetoplayer character stopmoving(); } else { zepetoplayer character movecontinuously(movedir); } if (player state === characterstate jump) { if (zepetoplayer character currentstate !== characterstate jump) { zepetoplayer character jump(); } if (player substate === characterjumpstate jumpdouble) { zepetoplayer character doublejump(); } } } private sendtransform(transform unityengine transform) { const data = new roomdata(); const pos = new roomdata(); pos add("x", transform localposition x); pos add("y", transform localposition y); pos add("z", transform localposition z); data add("position", pos getobject()); const rot = new roomdata(); rot add("x", transform localeulerangles x); rot add("y", transform localeulerangles y); rot add("z", transform localeulerangles z); data add("rotation", rot getobject()); this room send("onchangedtransform", data getobject()); } private sendstate(state characterstate) { const data = new roomdata(); data add("state", state); if(state === characterstate jump) { data add("substate", this zepetoplayer character motionv2 currentjumpstate); } this room send("onchangedstate", data getobject()); } private parsevector3(vector3 vector3) unityengine vector3 { return new unityengine vector3 ( vector3 x, vector3 y, vector3 z ); } } 👍 conseils ce guide n'implémente que la synchronisation de position la synchronisation des gestes, la synchronisation des objets, etc , n'ont pas été implémentées le principe est le même pour tous, mais le processus d'envoi et de réception des messages de salle à chaque moment requis est nécessaire si vous souhaitez implémenter la synchronisation de manière plus pratique, envisagez d'utiliser un module de synchronisation multiplay