IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement 2D, 3D et Jeux Discussion :

Le réseau dans les jeux vidéo : UDP vs TCP


Sujet :

Développement 2D, 3D et Jeux

  1. #41
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    @Neckara, si on prévoit (dès le début) de passer éventuellement de TCP à UDP par la suite, alors le choix est fait dès le début : ça va forcément influencer le design. Et si on le prévoit pas, il y aura une étape de refactoring assez monstrueuse quand on décidera de passer de l'un à l'autre.

    C'est pareil pour l'optimisation et le multi-threading : certaines choses doivent être pensées dès le début : même si on à qu'un seul thread dans un premier temps, il faut que le code soit pensé pour le multi-threading.
    Pour l'optimisation il y à "2 niveaux" :
    • macro optimisation : améliorer un algo pour passer d'une complexité en O(n²) à une complexité de O(n ln(n)) par exemple -> ça n'entraine généralement que peu de modifications (le corps d'une fonction qui change).
    • micro optimisation : réduire le nombre de cache misses, réordonner les instructions etc... -> changer la façon dont sont organisées les données ça peut avoir des conséquences énormes qui vont se répercuter sur une grande partie du code.


    Pour le parallélisme c'est un peu pareil :
    • threads : avoir par exemple un thread qui met à jour les objets, un autre qui les affiche, mais on peut aussi avoir une granularité plus fine: la mise à jour d'un objet est une tache atomique qui sera confiée à un threadpool, la maj de x objets sera effectuée par y threads. Si le code n'est pas pensé pour dès le départ on aura des synchronisations partout ce qui va ruiner tout gain apporté par le multi-threading.
    • vectorisation : mettre à jour les objets 1 par 1 c'est bien, mais 4 par 4 c'est mieux. Encore une fois si les données ne sont pas organisées avec ça en tête, ça sera soit impossible, soit on n'en profitera pas correctement.


    Ce sont vraiment des choix de design à faire très tôt.

    Pour ton exemple, tu auras bien 2 arbres, mais 2 arbres de "demi-objets" : ils seront divisés en 2 parties distinctes (affichage / gameplay). -> Les ECS poussent le principe plus loin en ayant un arbre pour chaque aspect d'un objet.

    (exemple très schématique)
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    struct RenderComponent { /* ... */ }; // toute la partie d'un objet liée à l'affichage
    struct GameplayComponent { /* ... */ }; // l'autre partie de l'objet, lié au gameplay
     
    std::vector<RenderComponent> rs;
    std::vector<GameplayComponent> gs;
     
    std::thread gameplay([&gs]() {
    	while(1) {
    		// mise à jour des objets, on ne touche que la partie GameplayComponent
    		for(auto& g: gs) {
    			// ...
    		}
    	}
    });
     
    // thread principal qui gère l'affichage
    while(1) {
    	// maj des RenderComponents à partir des GameplayComponents (besoin de synchro)
    	// ...
     
    	// puis affichage des RenderComponents, qui s'effectue pendant la maj des GameplayComponents par le second thread
    	for(auto const& r: rs) {
    		draw(r);
    	}
    }

    Si cette séparation des objets en 2 parties n'est pas pensée dès le début, il sera difficile de multi-threader les traitements si les besoins s'en font sentir.

  2. #42
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    @Neckara, si on prévoit (dès le début) de passer éventuellement de TCP à UDP par la suite, alors le choix est fait dès le début : ça va forcément influencer le design. Et si on le prévoit pas, il y aura une étape de refactoring assez monstrueuse quand on décidera de passer de l'un à l'autre.
    Je pense qu'on est d'accord sur le fond, mais pas sur les mots.

    On peut faire le choix de ne pas faire de choix au début, ie le choix de commencer en TCP puis de passer en UDP si on a le temps, si on veut commencer à distribuer le jeu, si … Donc oui, on va le prévoir au début pour faire un choix définitif final plus tard.

    C'est pareil pour l'optimisation et le multi-threading : certaines choses doivent être pensées dès le début : même si on à qu'un seul thread dans un premier temps, il faut que le code soit pensé pour le multi-threading.
    Il faut surtout faire des tests. On ne peut pas tout prévoir, donc on va essayer de garder un maximum de portes ouvertes.

    Après, pour l'optimisation, il est impossible de tout penser au début. Donc on va essayer de tester au maximum pour faire un choix. Mais on ne fait pas le choix avant d'avoir testé.



    changer la façon dont sont organisées les données ça peut avoir des conséquences énormes qui vont se répercuter sur une grande partie du code.
    Est-ce qu'il n'y a pas dans ce cas un début symptomatique de couplage fort (?)

    Si le code n'est pas pensé pour dès le départ on aura des synchronisations partout ce qui va ruiner tout gain apporté par le multi-threading.
    Il n'y a pas trop de mystères, il faut le réécrire. D'où l'importance de tester.
    Mais avoir un code propre bien découpé peut énormément aider à la refactorisation je pense.

    Pour ton exemple, tu auras bien 2 arbres, mais 2 arbres de "demi-objets" : ils seront divisés en 2 parties distinctes (affichage / gameplay).
    J'ai du mal à visualiser ce que tu entends par là.

    Si cette séparation des objets en 2 parties n'est pas pensée dès le début, il sera difficile de multi-threader les traitements si les besoins s'en font sentir.
    Après, ce sont des bonnes pratiques, plus que des choix. Faire que le code soit le plus propre et le plus évolutif possible.

    Mais faire ces choix, demande aussi une grande expérience et on est jamais à l’abri d'erreurs.

  3. #43
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Pour moi, cela rentre dans un choix d'architecture, plus que dans un choix TCP ou UDP. En effet, on a pas encore fait le choix final, mais on sait qu'on va en faire un. Bien que ce choix d'architecture soit en effet très important.
    Comme je l'avais mentionné on sait à l'avance s'il faudra une solution UDP ou non. C'est donc davantage un choix d'agenda que d'architecture.

    Et puisque ta solution impose quand même d'adopter 75% des coûts d'UDP dès le début du projet, tu n'as fait que repousser la "date de paiement" des 25% restants. C'est un choix trop coûteux pour être fait "pour voir".


    Pour des jeux 2D, on a à peu près la garantie que cela tournera sur un seul thread (?).
    C'est plus pour la 3D que cela pose problème ?
    La 3D nécessite certainement des calculs plus lourds en général mais je ne crois pas que ce soit le facteur déterminant. En effet si tu veux faire un pendu en 3D il y a peu de chances que tu aies besoin d'une archi parallèle de fou. Par contre si tu veux faire un Dwarf Fortrees en Ascii art, avec sa gestion des fluides à l'échelle d'un monde, son réseau de pathfinding avec des milliers d'acteurs et ses optimisations logistiques des inventaires... Bonne chance.


    Ce que je veux dire, c'est que à partir du thread gameplay, on va générer un arbre de tous les trucs à dessiner qu'on va ensuite donner au rendu pour qu'il dessine le tout, … (?)

    Donc au final avoir 2 arbres A et B (?)
    Pendant qu'on en édite A côté gameplay, on dessine B dans le thread de rendu ?
    Puis on synchronise A et B en copiant A dans B ?
    On ne copie pas, on transfère simplement la "propriété" de l'objet en s'engageant à ne plus y accéder ensuite depuis le thread de départ. Et si tu as bien deux arbres, ce sont deux arbres différents avec des types différents (Actor d'un côté, MeshRenderer de l'autre).

    Ce concept de transfert de propriété est abstrait. En Rust il serait prouvé par le compilateur et ne nécessiterait alors aucun artifice. En C++ on utiliserait un unique_ptr (ce qui revient à une preuve). En C#/Java on ajouterait en mode debug un identifiant de propriété et on vérifierait l'identité du thread à chaque accès de l'objet.

    Cela dit ce genre de solutions de synchronisation peut dans certains cas impliquer des copies, oui. Par exemple pour communiquer les nouvelles positions.


    Citation Envoyé par Neckara Voir le message
    Est-ce qu'il n'y a pas dans ce cas un début symptomatique de couplage fort (?)
    Si tu veux dire par là que ta volonté de paralléliser va influer sur ton archi, oui. Mais c'est toujours le cas des optimisations significatives : optimiser c'est réécrire le code.

    Fort heureusement dans la plupart des cas la parallélisation demande une intervention minime et aboutit même souvent à un code plus propre : moins de mutabilité, ou des mutations bien circonscrites à un appel, signifient souvent moins de bogues. Raison pour laquelle un langage comme Haskell a incorporé l'existence de modifications d'états dans le système de types (le monade IO encapsule un lambda qui effectuera des modifications) tout comme C++ a incorporé l'immutabilité des valeurs individuelles dans le sien (mot-clé const) - même si à mon avis ces deux choix ne sont pas rentables pour la plupart des projets.

  4. #44
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    En pratique, avec une vraie lib réseau, le switch peut être très simple : la lib réseau se charge de repacketer les datagram ou packet et les expose ainsi au reste de l'application, qui n'a cure de savoir si c'est TCP ou UDP derrière, si ça a été fragmenté, renvoyé suite à une perte, etc...
    Seule l'initialisation change.

    Ce qui diffère beaucoup par contre c'est l'utilisation... on n'aura pas la même utilisation d'un socket connecté à un serveur que d'un socket utilisé en P2P et peut recevoir les données de plusieurs clients.. et ça, ça s'improvise pas.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. Le réseau dans les jeux vidéo : Fiabilité, ordonnancement et congestion
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 2
    Dernier message: 03/06/2015, 01h53
  2. Le réseau dans les jeux vidéo : Connexion virtuelle en UDP
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 0
    Dernier message: 17/05/2015, 17h59
  3. Le réseau dans les jeux vidéo : Envoyer et recevoir des paquets
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 0
    Dernier message: 03/05/2015, 19h10
  4. Réponses: 88
    Dernier message: 01/09/2012, 13h15
  5. Du réseau dans les jeux
    Par Mathieu.J dans le forum Développement
    Réponses: 3
    Dernier message: 07/05/2004, 16h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo