Bonjour,
Sur la prédiction des lags pour NPC, weapons etc.. il y a plein d'article sur le wiki de valve avec du code.
http://developer.valvesoftware.com/wiki/Prediction
Nous l'avons déjà utilisé dans un projet, cela marche assez bien.
Bonjour,
Sur la prédiction des lags pour NPC, weapons etc.. il y a plein d'article sur le wiki de valve avec du code.
http://developer.valvesoftware.com/wiki/Prediction
Nous l'avons déjà utilisé dans un projet, cela marche assez bien.
Bonjour, je me permet de demander votre aide!
J'ai bien lu tout ce qui étais posté jusque là avec les liens anglais bien que j'y pige pas grand chose mais je n'avance pas dans mon jeu .. J'ai du mal à cerner comment faire pour arriver à synchroniser ne serait-ce qu'un client et le serveur ..
Bon je vais déjà poser la situation. Je veux faire un jeux style MMORPG en
side-scrolling genre Terraria pour ceux qui connaisse.
Si la communication entre le serveur et le client à une latence de 2sec, est ce que tous les packets UDP que je vais avoir envoyé depuis le client vont s'entasser sur le serveur jusqu'à avoir été tous traités par ce dernier ? (Il me semble que oui d'après mes observations mais je suis pas sûr)
Actuellement j'envoie à chaque tour de boucle de mon client les entrée claviers correspondant au contrôle du jeu sous forme de booleans dans un Packet à mon serveur. Est ce une bonne solution ou devrais je faire autrement ?
A chaque tour de boucle du serveur j'envois à tous les clients les positions actuels de tous les éléments que je souhaite actualisé ainsi que leur vecteurs de déplacement (pour le moment cela se limite au joueurs). Je suis pas du tout convaincu qu'il faille faire cela mais je ne comprends pas comment procéder ...
Voilà j'ai sûrement oublier des questions mais je vais pas vous surcharger ^^ Si vous pouviez déjà m'aider sur ces quelques point je vous en remercierais fortement
Edit : Ah oui j'ai choisi d'envoyer les Input parce que j'ai déjà vu que ça se faisait et je sais aussi que via un PacketSender on peut injecter au serveur de faux vecteur de vitesse ou de position et donc tricher d'où mon choix mais si y'a mieux je suis preneur lol..
Edit 2:
Bon j'ai essayez d'analyser comment le programme se comportait dans network physics (téléchargeable en bas de la page) mais décidément le système d'historique m'échappe..un post très intéressant que je vais compléter par un lien que quelqu'un du forum m'avait déjà donné il me semble (IrmatDen ?) : networked physics (en Anglais). A noter que la dicussion qui s'engage dans les commentaires à la suite de l'article est également à lire
Autre mine d'informations de 1er choix: le site de Valve qui détaille les mécanismes mis en oeuvre dans leur moteur réseau du moteur de jeu qu'ils commercialisent (celui d'Half Life 2 et de Counter Strike Source): ici et là (en Anglais, toujours).
Je comprends à peu près que le serveur regarde dans le sien dès qu'il reçoit une mise à jour d'un client pour voir l'état du jeu à ce moment là (packet daté ? et comment ?) mais j'ai du mal à comprendre ce qu'il faut faire ensuite ..
Le client doit "corriger" d'après ce que le serveur lui envoie mais comment faire pour pas que les nouvelles positions provoques de saccades ? Erf je dois être mou mais j'avoue que là ... Enfin bref si vous pouviez m'aidez ça serait vraiment cool xD
Cordialement,
Kalast.
Je fais un petit UP en espérant qu'on me réponde .. ^^.
SI j'envoie que les input du client au serveur, le client n'effectuant pas ses déplacement à la même vitesse, je me retrouve à des positions totalement différentes dans certaines situations.. Par exemple sur mon client je vais retrouver sur une plateforme alors que sur le serveur je passerais en dessous.
Comment faire pour palier cela ? J'envoie au serveur les inputs, ma position et mes vecteurs de vitesses et le serveur verifiera si le déplacement est correct en fonction du ping du client ? (Si la vitesse et trop élevé par rapport au ping on ignore le packet par exemple ?) Mai si le packet est ignoré, j'aurai un décalage de nouveau non ? Erf je m'embrouille de plus en plus j'ai l'impression donc si on pouvait m'aider à y voir plus clair avant que je n'explose lol.
Merci !
je te donne une idée de ce que je ferai à ta palce :
tu connait la vitesse maximale de déplacement
le client envoie une position qui n'est pas possible d'après tes calculs
tu tronques cette position par la position intermédiaire correspondant à un déplacement à vitesse maximale
et tu envoies le DELTA de cette position au client qui DOIT se repositionner par rapport à ce delta
Donc pour savoir déjà, dans mon packet client -> serveur j'envoie un X et un Y.
Le serveur reçoit cette position et regarde où le joueur se situait avant la réception et il en déduit si le déplacement est réalisable ou non.
Si le déplacement est possible, le serveur enregistre la nouvelle position du client.
Sinon, il lui renvoi un packet avec la position corrigée.
Le client reçoit le packet en question et recadre sa position sur ses données.
Comme ça c'est bon ?
Ensuite les autres clients reçoivent également la nouvelle position du joueur et via un algorithme simuleront le déplacement du joueur de l'ancienne position connue à la nouvelle (pour éviter de voir le joueur se "téléporter à cause du lag").
Edit : Par contre c'est toujours valable si le client subit de grosse pertes de performances ? Par exemple un client fonctionnant à vitesse optimale va "update" sa position toutes les 16 ms, par contre si un autre client parcours sa boucle en 32 ms par exemple, il va effectuer un déplacement 2 fois plus grand et envoyer sa nouvelle position qui sera perçu comme deux fois trop rapide par le serveur non ? Car le serveur est pas censé savoir que ce client à des soucis de perfs ou on peut palier cela d'une quelconque maniere ?
Merci de m'avoir répondu en tout cas^^
c'est bon à un détail près : comme je disais dans ma réponse, ma façon de faire serait que le serveur renvoie un delta, c'est la différence entre la position chez le client et la position que le serveur valide
Dans les paquets que ton client et ton serveur échangent, il doit toujours y avoir un "tick", ou si tu préfères, un indicateur de temps
à la connection, le client doit se synchroniser avec le serveur pour les échanges
et le serveur doit savoir entre 2 informations, combien de temps s'est écoulé sur le client
sinon tu ne peux clairement pas valider tes calculs
Ok ok ^^ Je vais essayer comme ca alors.
Par contre quel unité de temps ce "tick" ?
Genre à la connexion du client, le serveur envoie un [System.currentTimeMillis() - timeUpdate] représentant le temps écoulé depuis le démarrage du serveur dans un packet.
Le client reçois le packet et stocke le tick dans une variable par exemple lastTimeServ.
Puis quand le client renvoie une information il ajoute dans le packet un [lastTimeServ + timeSinceLastUpdate] représentant le dernier temps du serveur connus + temps écoulé depuis la réception de ce dernier.
Avec des chiffres ça donnerait ça :
1) On initialise la variable timeUpdate sur le serveur avec un System.currentTimeMillis().
2) On reçoit la connexion d'un client donc on lui envoie le packet de synchro avec notre tick qui devient égal par exemple à 14000.
3) Le packet arrive au client et on stocke alors notre tick dans la variable lastTimeServ et dans le même temps on initialise notre variable timeSinceLastUpdate avec un System.currentTimeMillis().
4) Le client renvoie un packet au serveur avec le nouveau tick sera égal à 14000 + 32 soit 14032 millisecondes.
5) Le serveur reçoit le packet, il estime donc que le client à mis 32 millisecondes avant de renvoyer l'information.
Je pense que c'est l'idée mais j'ai l'impression de faire trop compliqué .. Dis moi si je me trompe lol.
Edit : Est ce que cette solution intègre le fait que mes déplacements soit progressifs ? Le personnage dans mon jeu n'est pas à vitesse maximum au premier appui de la touche mais au bout de 5 tour de boucle par exemple en gardant la touche enfoncée ce après quoi il décélère (une fois la touche relachée bien sûr) a nouveau progressivement mais pas forcement à la même fréquence.
l'idée est là, même si ça semble compliqué à mettre en oeuvre
pour le tick, je pensais à la milliseconde
je pense aussi qu'on peut essayer de simplifier le système :
pour la synchro client/serveur :
- le client initialise un compteur de temps lorsqu'il se connecte
- à chaque fois que le client envoie une information au serveur, le client inclus son compteur de temps
- le serveur reçoit une info (position par exemple) et vérifie que la différence de position concorde avec le temps passé et la vitesse maximale possible
si tu veux gérer la possibilité de tricher, tu peux ajouter ce calcul qui nécessite un peu de synchro :
- le serveur a un compteur de temps qui démarre lorsqu'il est lancé
- le serveur mémorise l'heure à laquelle un client s'est connecté
- le serveur vérifie que le temps ne s'écoule pas trop vite côté client
si le serveur considère que le temps s'écoule trop vite, soit tu essaies de recaler le client, soit tu le déconnecte (plus simple)
nb : tous les temps sont en millisecondes
Ok je vais essayer de mettre ça en place. Selon toi je devrai envoyer mon infos de position à quelle fréquence ? Parce que si je le fait à chaque tour de boucle du client je vais bouffer une bande passante monstrueuse et risque de saturé le serveur j'imagine.
Encore avec deux clients ça peut passer mais au delà je crois qu'il va pas trop aimer mdr. Le but étant d'acceuillir quand même beaucoup de joueurs. Après je suis conscient qu'en hébergeant moi même le serveur faut pas s'attendre non plus à une latence de 50 ms entre les clients communiquant à travers le net lol.
Mais si je pouvais acceuillir déjà une bonne dizaine de joueur et supporter une latence d'un maximum de 100 ms c'est peut être possible en gérant bient le transit des données. Reste à connaître la fréquence optimale d'envoi de celles ci. Je ne sais pas ce qu'il en est pour les autres juex du genre minecraft, terraria ou autres. J'ai bien essayé de me renseigné mais sans succès pour le moment.
Par la suite si le serveur est bien optimisé je me tournerai vers une solution de serveur dédié pour avoir une meilleur fludité.
Je te tiens au courant pour le reste merci encore ^^
Bonjour j'ai lu la discussion(ok une seule fois pour le moment, je relirais il faut que ca rentre^^)
Je pense avoir compris le but qui est que le serveur garde des states précédent de ses clients. Car un joueur fait une action (decisive) alors on check par rapport a un state précédent pour savoir ce qui se passait a cet instant dans la réalité du client.
Maintenant concernant l'interpolation et l'affichage.
- Si un joueur tire, je trouve ca plus interessant de faire partir la bullet directement sur le client local. Du coup le serveur peut recevoir dans un cas critique l'information, 500 ms plus tard ensuite le temps qu'elle arrive a un autre client lambda il y aura peut etre 520ms.
Si c'est un projectile lent(ex:boule de feu) alors que fait le client lambda?
Il l'affiche la balle directement a:
POS_CLIENT_LOCAL + LAG * SPEED?
Du coup au lieu que la balle parte du joueur local elle va partir avec un offset.
- En ce qui concerne les techniques d'interpolations de mouvement, le joueur avance les autres client interpole sa position par rapport a sa vitesse, mais si le joueur change brusquement de position alors il va y avoir un TP au prochain packet recu. Que faire?
Aussi pour mes développement j'aimerai me mettre dans la situation d'un vilain qui a un mauvais ping, existe-il des technique pour simuler le lag autre que par le code de l'appli en question.
Merci de votre aide.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager