• Jeux Vidéo
  • Toi aussi deviens indéveloppeur [Unity/UE4 pour platformers 2D osef]

hichlibedis
hichanbis

Une semaine que je passe sur mon algo de combat au tour par tour en me prenant la tête (entres autres choses).
Quand je passe enfin à l'utilisation des Coroutines (le concept me faisait un peu peur), problem solved en 15 minutes.
Cette puissance.
1408.gif

Edit par hichanbis (24 Nov 2015)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 24 Nov 2015

ez les coroutines smiley45

Gaffe de pas faire l'erreur de base : Les coroutines ne sont PAS des threads. N'utilises pas de coroutines pour charger des trucs en pensant que ton jeu va tourner sur le coté en mode pépère.

hichlibedis
hichanbis

Binouz - 24 Nov 2015

Pour l'instant je comprends ça comme une fonction Update (ou le yield return null te permet d'attendre la prochaine frame) et sur laquelle tu peux foutre des tempo, donc pratique pour séquencer les actions.
Et du coup quand je fais un StartCoroutine mon code attend l'exec de la coroutine donc oui c'est pas un thread.
Si j'ai mal compris corrige moi stp.

Par contre j'ai du mal avec l'instruction yield.
J'ai compris que yield return null = pause et attend la prochaine frame.
yield return new waitForSeconds(n) = pause une durée fixe
yield return StartCoroutine(toto) = execute la coroutine toto et attend la fin

Mais parfois je vois
yield return toto (sans préciser startcoroutine)
Ca consiste en quoi?

Edit par hichanbis (24 Nov 2015)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 24 Nov 2015

Non c'est exactement ça, dire qu'à SIG je dois passer une journée entière pour qu'ils comprennent ces 4 pauvres phrases pepe_cry

Pour le reste de ta question , on peut pas (à ma connaissance), utiliser yield sans retourner un truc derrière. Le yield tout court, je crois que c'est en javascript.
J'pense que ces methodes que tu vois sans le return sont les équivalents javascript des méthodes juste au dessus.

EDIT : Ah du coup t'as édité feelsbad Ben sinon yield return toto, c'est pour retourner toto à l'IEnumerator. En fait IEnumerator c'est une interface C# qui permet d'énumérer des choses et parfois t'as envie de passer des valeurs précises pour récupérer des trucs depuis l'interface, comme savoir ou ça en est. C'est franchement avancé et pas super utile.

Edit par Binouz (24 Nov 2015)

hichlibedis
hichanbis

Binouz - 24 Nov 2015

Ok compris merci.
Oui, souvent je ninja édite au fur et à mesure de ma compréhension!

Binouz a écrit :

hichanbis - 24 Nov 2015
Non c'est exactement ça, dire qu'à SIG je dois passer une journée entière pour qu'ils comprennent ces 4 pauvres phrases pepe_cry

Tu peux pas comparer une démarche autodidacte motivée et des élèves qui se mangent un concept nouveau à 9h du mat' sans avoir rien demandé à personne.
C'est quoi SIG d'ailleurs?

Edit par hichanbis (24 Nov 2015)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 24 Nov 2015

SupInfoGame, à Valenciennes. Et c'est pas tant que ce soit des élèves (ils sont d'ailleurs majoritairement motivés pour écouter) c'est juste que c'est des game designer, et que pour une bonne majorité de la classe, les concepts basiques de prog sont loin d'être acquis. feelsbad

Et bien sur ils ont des cours Unity avant d'avoir des cours de prog (quand ils en ont), parce que sur Unity pas besoin de coder pour réaliser un prototype, c'est bien connu smiley122 Je crois que ça change d'année en année, ça va de mieux en mieux, l'école à compris que ça devenait difficile de trouver du boulot en tant que GD sans coder un poil. Bref smiley3

Edit par Binouz (24 Nov 2015)

hichlibedis
hichanbis

Hola, problème du jour, l'indépendance de la GUI.
J'ai lu quelque part qu'une best practice c'est d'avoir une GUI "indépendante", à savoir que t'enlèves la GUI ton jeu continue de tourner.
Vous confirmez le concept?

On fait comment dans la vraie vie? Parce que ça veut dire que les objets liées aux mécaniques de gameplay ne doivent pas appeler de méthodes liées aux objets de GUI.
Ce qui me paraît assez ingérable.

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

Ben ça dépend du niveau de rigueur que tu veux mettre dans ton code. Pour le coup c'est juste une question de confort : Si tu dois être amené à revoir entièrement ton système de GUI, tu gagneras du temps si tu as tout séparé que si t'as tout mélangé.

De base ce que je conseille de faire, c'est de toujours travailler en mode Manager/Controller. C'est à dire que tu as un script qui est le manager, par exemple HUDManager, qui est l'UI principale de ton jeu. Ben donc tu fais un script HUDManager qui a en variable tout cela, les sprites, les textes, tous les machins d'affichage. Ce manager est unique, c'est un singleton.

Et ensuite tu fais un HUDController, un pti script que tu peux foutre partout ou t'as besoin de récupérer des infos, c'est lui va chercher l'info nécessaire et qui l'envoie au manager. Tu peux faire plusieurs déclinaisons en faisant de l'héritage (HUDControllerLifebar, HUDControllerItem, etc).

De cette manière la classe MonHeros par exemple ne fait jamais d'appel à la GUI. Et quand y a un event spécial à faire et que ça doit être appelé par le héros, je passe par les event C# :

https://msdn.microsoft.com/en-us/librar … s.71).aspx

Ca me permet de faire des appels sans en avoir rien à foutre de ce qui va se passer derrière, si aucune classe ne s'est inscrit à l'evenement, il ne se passe rien. Si je dois changer toute ma GUI, j'ai juste besoin de changer la méthode que cet évènement va appeler.

C'est ma façon perso de fonctionner, tu peux aussi très bien simplement vérifier que ta GUI existe grâce à un simple "== null" à chaque fois que tu fais appel à ton manager d'UI. A chacun ces petites habitudes, sa façon d'organiser son code et voir jusqu'à ou t'es prêt à aller pour simplifier un truc qui n'arrivera ptet jamais (aka "merde, je dois refaire toute l'UI")

Edit par Binouz (26 Nov 2015)

L'IA de la nuit dernière
hichlibedis
hichanbis

Binouz - 26 Nov 2015

Ok mais donc t'as quand même un objet HudController réferencé dans des scripts de "gameplay" donc. C'est bien ça?
Pour parler concrètement,

Imaginons par exemple, un Gameobject BattleUI qui contient un panel avec les skills de mon perso et qui est caché (alpha = 0) par défaut.

1 - Je crèe un script BattleUIManager rattaché à ma BattleUI
Ce script contient toutes les réference dont mon skillsPanel.
Il peut contenir également une méthode populateAndDisplaySkillsPanel (qui prend en paramètre une liste de Skill et met alpha à 1 quoi)

2 - Maintenant pour les données j'ai un objet BattleManager qui instancie les unités de type player et donne un jeton à un joueur pour éxecuter des commandes il va donc falloir faire appel à BattleUI.populateAndDisplaySkillsPanel en lui donnant les skills non?

D'après ton explication je dois passer par un objet Controller? Il est réferencé où ? Il fait quoi?

Edit par hichanbis (26 Nov 2015)

L'IA de la nuit dernière
hichlibedis
hichanbis

Ok je vois mais du coup l'utilité du 3ème larron, le Controller dont parle Binouz?

L'IA de la nuit dernière
y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 26 Nov 2015

Ce que j'ai dis c'est ma façon de faire, et en me relisant je crois que j'étais complètement à coté de la plaque, me suis un peu embrouillé vis à vis de ta question smiley3.

Pour résumer en une ligne moi j'ai des un manager, qui gère des contrôleurs. Le manager réfléchi, le contrôleur agi. C'est ce que je voulais dire. Et quand j'ai besoin de communication direct, j'utilise des events C#.

Bref la façon dont t'as expliqué Tim est très bien smiley1 go faire ça.

Edit par Binouz (26 Nov 2015)

hichlibedis
hichanbis

Ouais en fait le modèle MVC où le modèle = mes classes serialisables, la vue BattleGUI et le controleur est le BattleManager.
Je vois, merci.

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

Exactement smiley4

hichlibedis
hichanbis

Merci pour les conseil ça marche nickel!
Après à mon avis c'est pas optimisé vu que ma BattleUI va chercher à chaque frame les infos des mes unités au lieu de juste être updaté ponctuellement quand il y a une attaque, mais bon c'est le prix à payer du modèle MVC je suppose.

Next: La navigation au pad dans la GUI smiley45

Edit par hichanbis (27 Nov 2015)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 27 Nov 2015

Ce qui est couteux en perf c'est de bouger la GUI à chaque frame, par exemple faire MyLife.text = "machin" a toutes les frames, ca bouffe. Une opti toute simple à faire si tu n'y as pas pensé c'est de mettre des conditions "si la valeur a changé, alors go" un peu partout juste avant.

Ca soulage le garbage collector, le moteur d'UI et la RAM, pour seulement le prix d'une minuscule opération de proc, bref, c'est tout benef :p

Edit par Binouz (27 Nov 2015)

hichlibedis
hichanbis

Ouais pas con, je modifie ce soir.

Invité(e)
Profil_supprime

Au taff j'ai fait un script tout con qui permet de calculer une approximation de la direction du joueur pour faire spawner des ennemis qui t'attendent cachés derrière les rues smiley120

Ça faisait longtemps que j'avais pas fait de trigonométrie ...

Sinon sur une note plus sérieuse, ne sait-on jamais.

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

Profil_supprime - 20 Dec 2015

GG smiley3

Pour quelle partie t'as utilisé la trigo ? Angle de camera par rapport au point de spawn ?

Invité(e)
Profil_supprime

Binouz - 20 Dec 2015

Nope, j'ai utilisé la trigo pour calculer un centre de gravité (ou barycentre) qui se base sur un nombre de vector définis au préalable (qui sont eux-mêmes des moyennes du forward vector du joueur + distance). A partir de ce point de gravité, je prends un radius pour décider où spawner les ennemis s'ils sont considérés comme occludés (je fais qu'un simple raycast entre le point et le joueur pour l'instant). Je me suis débrouillé pour pouvoir manipuler la précision du bordel, genre le nombre de moyennes de forward vectors, l'intervalle à laquelle c'est calculé, etc.

Après comme je dis, c'est assez simple et j'imagine que je peux faire ça plus proprement mais bon, en une petite aprem, ça fait déjà le café.

Fier comme un beauf.
Marks

quelqu'un a essayé superpowers ?

la serpillère de RuLL_34
CluBpop

Quelqu'un a essayé Terror Engine ?

Invité(e)
hichlibedis
hichanbis

6 mois que j'avais pas touché à mon code source parce qu'il était trop dégueu, plat de spaghettis, des références de partout j'arrivais plus à réfléchir.
Grand bien m'en a pris.

La je suis tombé sur un tuto sur les Events, une sorte d'Observer Pattern du coup j'ai refactoré tout mon code.
https://unity3d.com/learn/tutorials/top … list=17117

Ça m'a pris 11h presque d'affilée mais c'est tellement propre et fonctionnel maintenant. Un vrai MVC qui se lit bien  pepe_cry

Je suis chaud patate pour enchaîner maintenant.

Edit par hichanbis (23 Oct 2016)

hichlibedis
hichanbis

Hello petite question: Comment je gère la définition/stockage de mon bestiaire point de vue statistiques (Att/Def/Int/...)?

Pour l'instant j'instancie mes monstrers avec des stats directement dans mon code avec des variables "en dur" mais je trouve ça assez ingérable surtout le jour où je voudrais rééquilibrer le jeu, ou quand je vais définir plusieurs "versions" du même monstre en fonction de la scène courante.

Je me dis que je devrais peut-être mettre tout ça dans des XML et désérialiser.. enfin je sais pas ça parait lourd quand même.
Donnez-moi des idées svp!

Edit par hichanbis (25 Oct 2016)

L'IA de la nuit dernière
hichlibedis
hichanbis

.O. - 25 Oct 2016

Oui je suis sous Unity.
J'ai trouvé cette solution là qui est sympa
https://theliquidfire.wordpress.com/201 … e-objects/

Par contre je me demande ce qui est le plus efficace point de vue perf entre du XML que tu déserialise en instances en mémoire une fois en début de scène ou cette solution à base de scriptable objects et CSV...

L'IA de la nuit dernière
y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

J'utilise Google Sheets pour Unity, ça marche super bien, par contre si t'as des gros tableaux ça peut mettre plusieurs secondes pour load. Pis dès fois Google Sheets il a pas envie tout simplement, pas terrible à garder pour une mise en prod, mais suffisant pour updater ton projet.

Mais imho, t'auras pas 50k ennemis, te casses pas trop le cul avec des scriptable object, un bon XML/CSV, un petit parsing au tout début, et zou.

Si t'as envie de 0 temps de chargement en plus, une solution "simple" (elle a l'air compliqué mais en vrai c'est une affaire de 20mn et après t'es tranquillax) :

- Tu fais un prefab avec juste un script "Bestiaire" qui contient une variable List<Monstre>, Monstre étant une classe que tu indiques comme Serializable ([System.Serializable] au dessus de la déclaration de la classe dans le script. C'est juste pour qu'Unity puisse afficher la classe dans l'éditor.

- Cette classe bestiaire tu la flag "ExecuteInEditMode" : https://docs.unity3d.com/ScriptReferenc … tMode.html

- Tu fais une fonction qui va chercher ton XML/CSV, qui parse tout et qui remplie la liste de Monstre.

- Execute ta fonction depuis l'editeur , en suivant ce pti script tout con pour appeler une fonction d'un script depuis l'éditeur (regarde pas la vidz, les scripts en dessous) : https://unity3d.com/learn/tutorials/top … -inspector

- GG, ton prefab est peuplé avec tous tes monstres de base dans l'éditeur. T'as plus qu'à rappuyer sur le bouton quand tu modif ton XML/CSV. Tu peux faire la même en tirant les datas de Google Sheet avec le plugin de Tim au dessus.

Edit par Binouz (25 Oct 2016)

hichlibedis
hichanbis

Ok merci pour vos réponses.
La petite solution pour peupler du prefab de MonsterData à partir de l'éditeur me plait bien.

Après faudra juste trouver une solution pour lier ces données avec mes vrais prefabs de monstres qui contiennent les mesh, les scripts etc mais bon ça va être être un truc à base de Resources.Load et du nom du prefab je pense.

Edit par hichanbis (25 Oct 2016)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 25 Oct 2016

Si tu prends la solution de la liste peuplé dans l'editeur, cette liste peut très bien être sur un script "MonsterManager", qui contient toutes les fonctions pour appeler un monstre etc. Ca peut être un singleton que tu peux appeler partout, par exemple "MonsterManager.instance.maFonction()", sans avoir besoin de le référencer nulle part smiley1 Du coup le manager pourra se servir de la liste directement.

Le mieux dans Unity c'est de se servir dans l'éditeur, alors évidemment tu vas pas t'amuser à le customisé pour un projet perso, ain't nobody got time for that, mais ce genre d'auto-peuplade des listes, ou des boutons magiques qui configurent l'éditeur comme il faut à partir de XML/Excels/Google Sheets, ça fonctionne vraiment bien et ça fait gagner un temps fou.

Edit par Binouz (25 Oct 2016)

hichlibedis
hichanbis

Binouz - 25 Oct 2016

Google sheet comment ça marche ça dl tout a la demande dans l'editeur et aussi au moment du build ? le plugin deserialise en objet a la volée?
C'est peut-être bête ce que je demande mais je comprend pas très bien comment se fait le lien en fait.

L'IA de la nuit dernière
hichlibedis
hichanbis

.O. - 25 Oct 2016

Limpide, merci.

hichlibedis
hichanbis

Question perf du jour (qui n'a peut-être aucun intérêt):

Qu'est-ce qui coute le plus cher, instancier 100 prefab via Resources.Load ou en instancier un en tant que template et le "cloner" 99 fois?
(Pour le clonage j'ai une petite méthode statique qui serialise en flux mémoire et deserialise dans un nouvel objet).

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 27 Oct 2016

Ressources.Load c'est long, 100 Resources.Load c'est très long, et ça sert pas trop à ça :p Les prefabs tu les link directement dans tes scripts dans les champs "public GameObject monPrefab".

Ou alors j'ai pas compris la question. smiley3

hichlibedis
hichanbis

Binouz - 27 Oct 2016
Le truc c'est que mon prefab est un template pour des éléments de GUI dynamiques.

Du coup j'étais plutôt parti sur des instantiate à partir du prefab ressource.

Pas bon?

Édit: nan mais en fait t'as raison c'est plus simple comme ça et ça évite le ressource.load.

Edit par hichanbis (27 Oct 2016)

y a-t-il qqun pour rebrancher le cerveau de binouz
Binouz

hichanbis - 27 Oct 2016

Bah en fait tu fais un script avec dedans

public GameObject prefabGUITemplate;

que tu associes dans l'éditeur avec ton prefab template

Et quand t'as besoin de faire un "clone" de ce template tu fais

GameObject monElementGUI = Instantiate(prefabGUITemplate, la_position, la_rotation) as GameObject;

et tu manipules "monElementGUI" ensuite, qui est une instance de ce prefab.

Ou alors j'ai toujours pas compris smiley12 Désolé si je réponds à coté de la plaque : Qu'est ce que tu veux faire exactement ?

Edit par Binouz (27 Oct 2016)

hichlibedis
hichanbis

Binouz - 27 Oct 2016

Si t'as raison j'ai ninja edit, mais pas assez vite apparemment.

Edit par hichanbis (27 Oct 2016)

L'IA de la nuit dernière
hichlibedis
hichanbis

.O. - 27 Oct 2016

Ok je garde ça sous le coude, par contre ça marche pas pour ma GUI de système de combat où c'est dynamique à chaque tour.
Les prefabs a instantier/détruire dépendent du tour précédent.

Exemple:
lost-odyssey-battle-pic-2.jpg

Le panel de gauche là il dépend du perso actif, et on peut imaginer qu'un sort encaissé au tour précédent (genre mute) va griser certaines abilités la fois suivante.

Edit: Quoique je pourrais instancier chaque bouton avec toutes les abilities possibles de mes unités (et leurs versions désactivées) en début de combat et piocher dedans à chaque tour...

Edit2: Il me semble que Disabled est une transition de button en fait...

Edit3: Ok en fait je me prends trop la tête, c'est pas si dynamique que ça. Une seule initialisation au Start puis à chaque tour juste mettre interactable à false sur les boutons si mon perso est mute.  Thanks les gens.

Edit par hichanbis (27 Oct 2016)

hichlibedis
hichanbis

Hello, toujours dans mes problèmes de GUI.

J'ai désormais mes différents panels, sélection des attaques, si tu cliques sur Magic ça ouvre le panel du choix de type de magie, puis celui de la cible, c'est nickel.
J'essaie de faire en sorte que quand le joueur appuie sur le bouton cancel, ça désactive le panel courant et ça réactive le panel précédent et je vois très bien que je peux le faire en trackant l'input dans la méthode update etc.

Cela dit un truc qui me paraît propre c'est d'utiliser l'event cancel dans le Standalone Input Module... Et ça j'ai Google mais aucune idée de comment faire.

Edit par hichanbis (29 Oct 2016)

L'IA de la nuit dernière
Fiché HS
Britney

On a des screens du jeu à Hichanbis histoire de voir son chara design? smiley1

L'IA de la nuit dernière
Kelevra04

Britney - 29 Oct 2016

+1000
T'auras bientôt des trucs à montrer ou une démo jouable ?

hichlibedis
hichanbis

Kelevra04 - 29 Oct 2016

Rdv dans un an.

hichlibedis
hichanbis

.O. - 29 Oct 2016
Le UIManager et les variables c'est bon déjà.
C'est comment checker l'event cancel que je demande en fait...

Edit par hichanbis (29 Oct 2016)

  • Jeux Vidéo
  • Toi aussi deviens indéveloppeur [Unity/UE4 pour platformers 2D osef]