Yep.
Je connais bien le top down (en tout cas dans d'autres contextes de développement qu'avec Unity).
Je ne vois pas la différence/intérêt entre :
- passer par un SendMessageUpwards qui va pousser vers le GameManager (les events étant a priori pas gratuit en temps d'exécution)
- invoquer une méthode du GameManager (qui est un singleton) pour véhiculer l'info
En dehors peut être de la possibilité d'intervertir des GameManager, mais on obtient la même souplesse si ya une interface qui régit les méthodes appelées pour "remonter".
Dans le premier cas tu as une liaison faible dans l'autre, une liaison forte.
En gros si jamais dans un autre projet tu te sert du même objet porte et que cette fois-ci ce n'est plus GameManager qui écoute cette évènement mais PorteManager (je sais pas ^^') et bien tu aura aucun soucis dans le cas où tu fait un appelle d'event.
Dans l'autre faudra tout rechanger les appelles.
En gros, le petit objet n'est pas sensé connaitre les gros, il gueule (emit) "On ma cliquer dessus, mais je sais pas quoi faire" et le GameManager qui écoute fait "Ah c'est a mon tour de jouer alors si on ta cliquer dessus voilà ce que je doit faire"
Dans le cas où tu as pas d'event c'est la porte qui appelle directement un truc du GameManager donc il sais quoi faire il fait sa forte tête du coup !
Alors que il est pas sensé tout savoir
(Je sais pas si j'ai été bien clair ^^', dans le cas contraire hésite pas ^^)
J'utilise des liens forts typés quand des objets interagissent de façon complexe.
Ex: un behavior SpaceShip doit connaitre SpaceShipBuilding pour interagir de façon complexe. Plusieurs appels de méthodes pour ouvrir une porte sur SpaceShipBuilding, amarrer le vaisseau sur une zone spécifique, etc.
J'utilise des liens forts non typés (genre une interface générique qui implémente une méthode qui sera appelée) quand un behavior peut interagir par un appel de méthode simple.
Ex: un behavior Button va triggerer n'importe quel objet qui implémente une interface, par ex. une Porte qui activera son ouverture. De façon interchangeable un bouton pourra activer une passerelle, une lumière, n'importe quoi qui hérite de la dite interface générique.
Petite parenthèse : j'ai développé tout un système basé sur ce principe d'interface générique avec des décorateurs de membres customs / inspecteurs spécifiques avant de découvrir un système qui m’apparaît plus puissant que mon implèm et qui est déjà intégré à Unity : les UnityEvent. Voir cet exemple : Unity3D - UnityEvent
Enfin j'utilise des liens faibles non typés (par l'intermédiaire d'un MessageManager) quand un behavior doit interagir avec un autre behavior mais qu'il est peu souhaitable à l'un de référencer l'autre. Par ex. quand un bouton posé dans un prefab souhaite interagir avec une porte qui se trouve dans un autre prefab. Faire le lien entre eux ne peut que se faire dans la scène sur les instances des dits prefabs ce qui peut être pénible à maintenir pour X raisons.
Ex: un behavior CrytalButton peut envoyer un message "OpenCrystalGate" via un singleton MessageManager. Un autre behavior CrystalGate est à l'écoute des messages "OpenCrystalGate" et va interagir s'il reçoit ce message spécifique.
Je suis probablement trés naïf en ce qui concerne le fonctionnement des langages "haut niveau" et tout ce qui a trait à l'"orienté objet", mais on ne peut pas depuis le script attaché à un objet modifier les paramètres d'un autre objet ? (et passer des paramètres d'un objet à l'autre ; ce qui revient d'ailleurs peu ou prou à la même chose :P)
("de mon temps" j'aurai p.ex. passé en paramètre de l'appel de la routine 'ouverture_porte' le numéro de la porte considérée, si le flag 'verrouillé' de cette porte était à 1 'ouverture_porte' aurait lancé 'mini-jeu_déverrouillage' --éventuellement associé à d'autres paramètres, si p.ex. le mini-jeu pouvait être lancé avec différents modes de difficultés, ce qui aurait pu là encore être trouvé dans les attributs de la porte-- et si le mini-jeu renvoyait "succès" alors la routine 'ouverture_porte' aurait passé le flag'verrouillé' de la porte à 0 ; lorsqu'on aurait ré-actionné la porte, le lancement de 'ouverture_porte' trouvant cette fois le flag'verrouillé' à 0, la routine aurait cette fois menée à l'ouverture de la porte ; qu'est-ce qui n'est pas possible du coup ici?)
Bon en tout cas, pour en revenir à la question de départ, pour moi l'interface (càd ici la "barre d'action", ou plutôt " fenêtre d'actions" si j'ai bien compris?) doit être une entitée bien séparée qui va faire la jonction entre les objets et les actions du joueur (oui, c'est un peu l'évidence même, lol, mais c'est important de garder l'idée clairement en tête je pense ).
En l'occurrence je verrai du coup les choses comme ça :
- ton objet 'porte' contient des paramètres comme '_vérouillée'(oui/non), '_fermée'(oui/non), éventuellement aussi un '_aspectGraphique' (bois, métal, grille...), un '_niveauDeRésistance', des '_pointsDeVie',...
- l'objet 'porte' inclus le script gérant les interactions, comprenant les méthodes relatives aux actions qu'on va pouvoir lui appliquer ('Ouvrir'{this._fermée=0}, 'Fermer' (soit l'inverse), 'Crocheter',...} et une méthode 'Interaction'
- la méthode 'Interaction' appelle la 'fenêtreDActions' en lui passant une liste de commandes possibles (p.ex.{"ouvrir","crocheter,"forcer","examiner"})
- 'fenêtreDActions' à pour comportement de faire apparaître la liste d'actions, de permettre au joueur d'en sélectionner une, et de retourner le numéro correspondant
- 'porte.Interaction' reçoit donc un numéro et en fonction lance différente méthode ('Ouvrir','Crocheter',...)
- 'porte.Crocheter' appelle le 'Minijeu', qui retourne s'il y a succès ou non ; si succés 'porte.Crocheter' passe 'porte._vérouillée' à 0.
La nuance est que (à mon humble avis, amis barbus en djellaba du bit et du design pattern passez votre chemin) Unity est un "mix" entre POO (Objet donc) et "Evènementiel" (Soirée mousse donc, ou pas).
Avec des objets mais aussi des aspects et des evènements.
Le tout mixé dans le monde 4D du jeu video (3D + Temps).
Un joyeux méli-mélo : d'où mon "oui mais non" !
Car ce que tu proposes "marche" mais va devenir vraiment lourdingue si chacun (objet) doit pousser son identité pour chaque action.
J'ai tordu le sujet par la notion de "delegatation en C#" et quand c'était "lache" via un event Manager.
Donc grosse maille en raccord avec ce que disait plus haut Tortuap. (sauf que lui a pris le temps de mettre les bons termes sur ces concepts, moi je préfère noyer le poisson (et c'est pas simple à noyer un poisson)).
Yep.
Je connais bien le top down (en tout cas dans d'autres contextes de développement qu'avec Unity).
Je ne vois pas la différence/intérêt entre :
- passer par un SendMessageUpwards qui va pousser vers le GameManager (les events étant a priori pas gratuit en temps d'exécution)
- invoquer une méthode du GameManager (qui est un singleton) pour véhiculer l'info
En dehors peut être de la possibilité d'intervertir des GameManager, mais on obtient la même souplesse si ya une interface qui régit les méthodes appelées pour "remonter".
Dans le premier cas tu as une liaison faible dans l'autre, une liaison forte.
En gros si jamais dans un autre projet tu te sert du même objet porte et que cette fois-ci ce n'est plus GameManager qui écoute cette évènement mais PorteManager (je sais pas ^^') et bien tu aura aucun soucis dans le cas où tu fait un appelle d'event.
Dans l'autre faudra tout rechanger les appelles.
En gros, le petit objet n'est pas sensé connaitre les gros, il gueule (emit) "On ma cliquer dessus, mais je sais pas quoi faire" et le GameManager qui écoute fait "Ah c'est a mon tour de jouer alors si on ta cliquer dessus voilà ce que je doit faire"
Dans le cas où tu as pas d'event c'est la porte qui appelle directement un truc du GameManager donc il sais quoi faire il fait sa forte tête du coup !
Alors que il est pas sensé tout savoir
(Je sais pas si j'ai été bien clair ^^', dans le cas contraire hésite pas ^^)
Oui c'est clair : ) (ça l'était même avant d'ailleurs ^^)
Mais entre une gestion par événement et une interface entre les deux je ne vois pas la différence.
Il n'y en a peut-être pas : deux concepts de liens faibles. (après tout il y a toujours 35 façons de bien faire).
Salut,
Pour ma part,
J'utilise des liens forts typés quand des objets interagissent de façon complexe.
Ex: un behavior SpaceShip doit connaitre SpaceShipBuilding pour interagir de façon complexe. Plusieurs appels de méthodes pour ouvrir une porte sur SpaceShipBuilding, amarrer le vaisseau sur une zone spécifique, etc.
J'utilise des liens forts non typés (genre une interface générique qui implémente une méthode qui sera appelée) quand un behavior peut interagir par un appel de méthode simple.
Ex: un behavior Button va triggerer n'importe quel objet qui implémente une interface, par ex. une Porte qui activera son ouverture. De façon interchangeable un bouton pourra activer une passerelle, une lumière, n'importe quoi qui hérite de la dite interface générique.
Petite parenthèse : j'ai développé tout un système basé sur ce principe d'interface générique avec des décorateurs de membres customs / inspecteurs spécifiques avant de découvrir un système qui m’apparaît plus puissant que mon implèm et qui est déjà intégré à Unity : les UnityEvent. Voir cet exemple : Unity3D - UnityEvent
Enfin j'utilise des liens faibles non typés (par l'intermédiaire d'un MessageManager) quand un behavior doit interagir avec un autre behavior mais qu'il est peu souhaitable à l'un de référencer l'autre. Par ex. quand un bouton posé dans un prefab souhaite interagir avec une porte qui se trouve dans un autre prefab. Faire le lien entre eux ne peut que se faire dans la scène sur les instances des dits prefabs ce qui peut être pénible à maintenir pour X raisons.
Ex: un behavior CrytalButton peut envoyer un message "OpenCrystalGate" via un singleton MessageManager. Un autre behavior CrystalGate est à l'écoute des messages "OpenCrystalGate" et va interagir s'il reçoit ce message spécifique.
Je suis probablement trés naïf en ce qui concerne le fonctionnement des langages "haut niveau" et tout ce qui a trait à l'"orienté objet", mais on ne peut pas depuis le script attaché à un objet modifier les paramètres d'un autre objet ? (et passer des paramètres d'un objet à l'autre ; ce qui revient d'ailleurs peu ou prou à la même chose :P)
Merci beaucoup de cette liste exhaustive de patterns et leurs cas d'utilisation, Tortuap!
Intéressant !
(Non, je ne suis pas mort, simplement pris sur un projet Android applicatif)
PS : Nival oui mais non :^)
C'est à dire ?
("de mon temps" j'aurai p.ex. passé en paramètre de l'appel de la routine 'ouverture_porte' le numéro de la porte considérée, si le flag 'verrouillé' de cette porte était à 1 'ouverture_porte' aurait lancé 'mini-jeu_déverrouillage' --éventuellement associé à d'autres paramètres, si p.ex. le mini-jeu pouvait être lancé avec différents modes de difficultés, ce qui aurait pu là encore être trouvé dans les attributs de la porte-- et si le mini-jeu renvoyait "succès" alors la routine 'ouverture_porte' aurait passé le flag 'verrouillé' de la porte à 0 ; lorsqu'on aurait ré-actionné la porte, le lancement de 'ouverture_porte' trouvant cette fois le flag 'verrouillé' à 0, la routine aurait cette fois menée à l'ouverture de la porte ; qu'est-ce qui n'est pas possible du coup ici?)
EDIT : ah, j'ai l'intuition que ça a un lien avec ça https://fr.wikipedia.org/wiki/Encapsulation_%28programmation%29
Décidément, la programmation "orientée objet" ç'a l'air bien compliqué pour pas grand chose ...
Bon en tout cas, pour en revenir à la question de départ, pour moi l'interface (càd ici la "barre d'action", ou plutôt " fenêtre d'actions" si j'ai bien compris?) doit être une entitée bien séparée qui va faire la jonction entre les objets et les actions du joueur (oui, c'est un peu l'évidence même, lol, mais c'est important de garder l'idée clairement en tête je pense ).
En l'occurrence je verrai du coup les choses comme ça :
- ton objet 'porte' contient des paramètres comme '_vérouillée'(oui/non), '_fermée'(oui/non), éventuellement aussi un '_aspectGraphique' (bois, métal, grille...), un '_niveauDeRésistance', des '_pointsDeVie',...
- l'objet 'porte' inclus le script gérant les interactions, comprenant les méthodes relatives aux actions qu'on va pouvoir lui appliquer ('Ouvrir'{this._fermée=0}, 'Fermer' (soit l'inverse), 'Crocheter',...} et une méthode 'Interaction'
- la méthode 'Interaction' appelle la 'fenêtreDActions' en lui passant une liste de commandes possibles (p.ex.{"ouvrir","crocheter,"forcer","examiner"})
- 'fenêtreDActions' à pour comportement de faire apparaître la liste d'actions, de permettre au joueur d'en sélectionner une, et de retourner le numéro correspondant
- 'porte.Interaction' reçoit donc un numéro et en fonction lance différente méthode ('Ouvrir','Crocheter',...)
- 'porte.Crocheter' appelle le 'Minijeu', qui retourne s'il y a succès ou non ; si succés 'porte.Crocheter' passe 'porte._vérouillée' à 0.
Ça doit fonctionner en "orienté objet" ça, non ?
La nuance est que (à mon humble avis, amis barbus en djellaba du bit et du design pattern passez votre chemin) Unity est un "mix" entre POO (Objet donc) et "Evènementiel" (Soirée mousse donc, ou pas).
Avec des objets mais aussi des aspects et des evènements.
Le tout mixé dans le monde 4D du jeu video (3D + Temps).
Un joyeux méli-mélo : d'où mon "oui mais non" !
Car ce que tu proposes "marche" mais va devenir vraiment lourdingue si chacun (objet) doit pousser son identité pour chaque action.
J'ai tordu le sujet par la notion de "delegatation en C#" et quand c'était "lache" via un event Manager.
Donc grosse maille en raccord avec ce que disait plus haut Tortuap. (sauf que lui a pris le temps de mettre les bons termes sur ces concepts, moi je préfère noyer le poisson (et c'est pas simple à noyer un poisson)).
Pages