M'sieurs dames,
J'ai plongé dans Unity depuis quelques temps.
Je m'en sors sans trop de problèmes (l'internet est foisonnant de questions/réponses permettant de régler les mini blocages etc).
J'ai néanmoins une question de fond sur laquelle je n'arrive pas à trouver de littérature.
Je sais bien qu'on n'est pas sur un site spécialisé mais j'aime bien ce forum alors j'en profite.
Ma question :
Quelle est la "bonne pratique" pour goupiller l'aspect "intelligence" (objets, attributs, méthodes utilitaires etc), l'aspect "gestion graphique" (placement, déplacement, rotation) et l'aspect "évènementiel" (moteur à état, gestion des inputs du joueur etc) ?
Je prends un exemple (car ma question est surement très floue) :
Imaginons un jeu 2D vu de dessus avec un personnage navigant dans des pièces fermées par des portes.
- J'ai un gameobject (en prefab) Porte qui est défini par un Sprite, un Collider2D, un script C# qui matérialise la porte (ouvert/fermé notamment).
- Quand je click sur la porte, ça ouvre un panel "pop up" qui permet de choisir des actions dont "déverrouiller". (panel avec un button qui gère le onClick)
- Quand je click sur le bouton "déverrouiller", cela ouvre un mini jeu qui si il est remporté ouvre la porte. Le mini jeu est instancié.
- Quand le mini-jeu est terminé avec succès la porte doit être ouverte.
Actuellement j'ai fait ainsi :
- La Porte a en référence la barre d'action.
- Quand je click sur la Porte le script de gestion de la barre d'action est appelé pour l'afficher au bon endroit en passant en paramètre la référence de la Porte.
- Le bouton de la barre d'action renvoie également vers le script de gestion de la barre d'action dans une autre méthode qui déclenche l'instanciation du mini-jeu (en passant en référence la barre d'action). Au passage je stocke l'action en cours.
- Quand le mini-jeu est terminé je fais un sendmessage vers la référence de la barre d'action.
- La barre d'action recoit le message et comme l'action en cours est "déverrouiller" elle fait également un sendmessage d'une méthode openPorte vers la Porte qui est en référence sur la barre d'action.
Ca fonctionne.
Mais je trouve que c'est un brin bricolesque.
Ya pas mieux en terme d'organisation logique ?
Ya-t-il de la litterature (livres inclus) démystifiant les bonnes pratiques (et/ou design pattern) pertinent dans le développement autour de Unity ?
PS : désolé du pavé, en espérant avoir été compréhensible.
PS2 : Bonne année et longue vie (et prospérité) à IndieMag
Merki d'avance : )
Edit : corrections de coquilles.
Je plussoie le sujet!
Je suis Dev Unity et j'ai des questions similaires aux tiennes. On m'a conseillé ce livre, mais il me paraît assez gros, et je ne suis pas sûr qu'il soit vraiment approprié dans la dev de Jeux Vidéo. Si quelqu'un a des listes de Design Patterns pour les Jeux Vidéo, je suis prenneur.
De mon point de vue de Dev (et de ce que je comprend de ton projet), je te conseillerais mettre un singleton dans la class de la Barre action, qui serait appellé dans le code de la Porte, dans la fonction Start() , à la création de la Porte. Cela implique bien sur que tu n'ais qu'une seule instance de Barre d'action.
Code de la barre d'action
Code de la Porte
On peut également imaginer que le code de la Porte instancie une Barre d'action, et que c'est la Porte qui va générer chaque bouton et callback dans la Barre d'action. Pour moi c'est à la Porte de générer et de contrôler tous les composants.
Le livre est très orienté POO. Or, dans Unity c'est hybride avec de l’événementiel d'où, j'ai l'impression, ma sensation d'être un peu perdu. (j'ai fait de l’événementiel et de l'objet mais le mixte entre les deux est ... particulier).
Pour le lien Porte <> Barre d'action, je suis en phase. Pour l'instant, vu que je jette des idées sans réellement faire propre j'ai simplement lié la barre d'action en attribut sur la porte via l'éditeur Unity (la porte n'est pas instanciée par script pour le moment). Mais l'idée reste la même.
Mon principal sujet de questionnement est sur l’enchaînement des trois morceaux : Porte > Barre d'action (dont bouton) > Minijeu.
Et plus particulièrement sur le retour.
Imaginons deux portes (ou d'ailleurs deux objets interactifs) : P1 et P2.
Chacun à différents moments peut faire surgir la barre d'action BA (unique on va dire) et donc accéder à l’instanciation du Minijeu MJ.
- P1 > BA > MJ
- P2 > BA > MJ
Comment concevoir proprement le retour du MiniJeu jusqu'à la porte pour l'ouvrir (autrement dit comment invoquer/appeler élégamment une méthode de la bonne porte lorsque le minijeu indique que c'est OK) ?
Pour l'instant la méthode la moins pire que j'ai trouvé c'est le passage par référence de la porte à BA et MJ est instancié en tant que fils de BA du coup ca donne :
P1 ==[appel avec p1] =>BA
BA ==[instancie en tant que fils] => MJ
MJ fait son job
MJ ==[sendMessage au parent, donc BA] => BA
BA ==[appel de méthode sur le gameobject fourni à l'appel] => P1
PS : du coup ça marche pour P2 (vu que c'est le même Prefab).
PS2 : J'aurai pu faire la même logique entre BA et MJ que celle réalisée entre P1 et BA d'ailleurs.
Ce qui me dérange c'est que la Barre d'action doit connaitre le type de l'appelant.
Ou alors je plaque une interface "Objet Interactif" et la barre ne gère que çette interface (ce qui est déjà nettement plus propre)
Le sujet en question est un exemple.
Mais c'est ce genre d'informations que je recherche. (j'ai le même type de questionnement pour les IA, GameManager, etc).
J'ai trouver une super liste de Design Patterns Unity c# sur Reddit:
https://www.reddit.com/r/Unity3D/comments/1nb06h/unity_design_patterns_and_concepts_looking_for/
En ce qui concerne ta question, je suis en train de regarder plus en détail comment les Events et les Delegates fonctionnent de manière à ne pas te dire de bêtises.
Sympa le lien. Je vais plonger dedans ASAP.
Je pense effectivement avoir trouvé une solution clean via la notion delegates et d'events.
http://www.indiedb.com/games/coco-blast/tutorials/delegates-events-and-singletons-with-unity3d-c
PS : le lien est tiré du lien d'Alex Krunch qui est une petite mine d'or.
Je colle ici un lien qui est "OMFG" sur la gestion des hexagones : http://www.redblobgames.com/grids/hexagons/
M'étant posé la question depuis pas mal de temps, et ayant reçu des cours sur Unity 3D, je peu répondre qu'avec mon expérience qui n'est pas une science exact ^^.
Pour moi il y a deux pratique sur Unity :
Soit tu programme avec de la composition =>
- Un GameObject à un script qui lui permet d'avoir de la vie par exemple (ce script pourra être donnée a un autre GameObject ayant lui aussi de la vie)
Ou alors tu programme (comme on me la appris) avec de la POO :
Le principe c'est que tu as des manager en singleton qui se parle entre eux avec des évènements.
Je m'explique : j'ai un GameManager, qui vas instancier un LevelManager qui lui vas se charger de gérer le niveau, par exemple en ce qui concerne ta porte :
La porte émet un évent lorsqu'on lui clique dessus, elle dit "On ma cliquer dessus", le LevelManager reçoit cette évènement et gère ce qu'il doit faire en fonction (dans ton cas il ouvre une pop-up qui fait sa sauce)
Et ainsi de suite ^^.
Je ne m'exprime peut être pas super bien si tu as des questions n'hésite pas
En POO C# les deux concepts auxquels tu fais allusion sont bien : le singleton (pour les managers) et la délégation (méthodes delegate) ?
Je suis parti sur cette logique depuis :
- Un GameManager en singleton qui centralise les échanges et qui exposent des méthodes déléguées
- Mes "personnages" s'abonnent aux méthodes déléguées
- Une hiérarchie (héritage) d'objets pour matérialiser mes "trucs" (mur, point d'intéret, porte, coffre)
- Les triggers (collider) sur les objets appellent une méthode sur le GameManager qui "broadcast" via les delegate et donc vers mes "personnages".
Il faut que je prenne le temps de poser le tout proprement pour alimenter ce thread.
J'ai d'ailleurs une question plus fourbe à poser (mais qui nécessite je pense que j'explique ma logique) pour gérer le déverrouillage puis ouverture de porte.
Oui pour le singleton.
Moi on m'a dit de faire du "Top-Down" je m'explique.
En gros les grosses classes on le droit d'appeler des méthodes de classes en dessous d'elle mais pas le contraire :
GameManager a le droit d'appeler une méthode de DoorManager (par exemple) mais pas le contraire (ça doit se faire par appelle d'évènement)
Ce que moi j'appelle les event c'est les méthodes déléguées si tu veux.
Du coup si tu veux suivre ce que je viens de dire(comme j'ai dit j'ai pas la science exact et mes profs non plus) t'es objets qui collide ne doivent pas appeler une méthode du GameManager mais ils doivent émettre un event.
Comment ce faire de manière simple : On nous a montrer une méthode pour émettre un message facilement des petits éléments de la scène jusqu'au manager.
En gros dans ta hiérarchie tu as un objet GameManager ou LevelManager qui as le script, a l'intérieur tu instancie tes petit éléments de sorte qu'il soit enfant du GameObject (dans la hiérarchie Unity et non enfant de manière POO attention ^^) De ce fait tu peu emmètre en faisant SendMessageUpward (je suis pas sur de la fonction mais ça ressemble ^^)
A voir si ça te va mais va pas tout cassé ton architecture actuelle pour faire ce que je te dit hein ^^, ce n'est qu'une façon de faire parmi d'autres
Pages