Partage
  • Partager sur Facebook
  • Partager sur Twitter

Unity - Problème avec les GameObjects

Sujet résolu
    24 août 2019 à 11:11:53

    Mesdames, messieurs, Bonjour. Je fais appel à votre savoir pour m'aider à régler un problème qui se présente à moi dans le logiciel et moteur de jeu Unity3D. En effet, j'essaie depuis quelques jours de développer un jeu de grande stratégie, dans le style de Crusader Kings II, ou Europa Universalis. Dans mon projet, comme dans ces jeux, les territoires seront divisés en fiefs, chacun ayant ses propres caractéristiques. Pour cela, j'ai créé une base de données pour simplifier la création de ces fiefs. Cependant, j'ai besoin, pour faire apparaître un onglet, de récupérer dans un script cet objet, et je n'y arrive pas. Que ce soit avec GameObject.Find("objet"), ou avec des tags, je n'y arrive juste pas. Donc je fais appel à votre savoir et votre bonté pour me venir en aide. Merci d'avance!

    • Partager sur Facebook
    • Partager sur Twitter
      24 août 2019 à 20:46:10

      Bonjour,

      Serait-il possible de donner des précision sur le type de base de données ?

      Par exemple pour Unity on peut considérer qu'un objet héritant de scriptable object est une base de donnée :

      https://learn.unity.com/tutorial/introduction-to-scriptable-objects

      Cela permet de faire une classe qui contient un ensemble de variable modifiable depuis l'editeur de Unity. Exemple :

      Pour ce qui est d'avoir acces a un fichier se situant dans les fichier de l'editeur. Vous pouvez le mettre dans un dossier nommé "Resources" (attention à ne mettre qu'un "S"). et utiliser Resources.Load("nom du fichier") qui chargera le fichier present dans le dossier Resources.

      Exemple pour mon cas : BlockScriptable monBlockScriptable = (BlockScriptable) Resources.Load("BlockDatabase");

      GameObject.Find("objet") permet d'avoir acces a un fichier dans la scene et non dans l'editeur. Il y a de plus d'autres moyens plus optimisés permettant de chercher un objet dans la scène (puisque GameObject.Find("") cherche parmis tous les GameObject de la scene).

      Vous trouverez ici dans un de mes paragraphes quelques moyens de referencer un autre Script ou GameObject (je conseil cependant d'utiliser une variable public et de le glisser dans l'inspecteur)  :

      https://openclassrooms.com/forum/sujet/poo-sous-unity

      Bonne journée

      -
      Edité par coukil 24 août 2019 à 20:48:14

      • Partager sur Facebook
      • Partager sur Twitter
        25 août 2019 à 9:37:51

        Bonjour M/Mme Coukil, Je vous remercie grandement de m'avoir répondu, et je m'excuse de répondre si tardivement. Donc, premièrement, ma base de données hérite bien de ScriptableObject. Elle sers à contenir les informations des différents fiefs, donc elle contient des bool pour savoir quel rang, un string pour le nom, un sprite pour les armoiries, et une référence à une autre base de données, elle contenant les informations de la nation du fief. ♦Le problème que j'ai avec cette première base de données, bien que je ne l'ais pas soulevé, je n'arrive pas à récupérer dans une variable image ou sprite une image. ♦Un autre problème auquel je suis confronté, c'est que je n'arrive pas à récupérer dans une autre variable le GameObject d'un onglet d'un canvas. Cependant, même en utilisant la commande "GameObject.Find("nom de l'objet")", celle-ci renvoie une valeur nulle. Merci d'avoir accepté de me répondre, bonne journée!

        • Partager sur Facebook
        • Partager sur Twitter
          25 août 2019 à 18:14:05

          Il serait utile d'envoyer des screenshot ou du code (avec l'aide de la mise en page proposé par le forum) et de préciser ce que vous souhaitez faire.

          Pour ce qui est de GameObject.Find(""), si il est possible, utilisez d'autres moyens qui permettent de referencer l'objet car GameObject.Find("") vas verifier parmis tous les objets de la scene lequel possède le nom de l'objet et n'est donc pas tres optimisé.

          Il serait possible que cela renvoie une valeur nulle car l'objet est inactif :

          https://stackoverflow.com/questions/19584127/how-to-find-inactive-objects-using-gameobject-find-in-unity3d

          Je ne peux pas aider plus sans informations supplementaires tel que du code ou des précision sur ce que vous souhaitez faire.

          Bonne journée.

          • Partager sur Facebook
          • Partager sur Twitter
            25 août 2019 à 19:11:51

            Alors, je vous remercie à nouveau pour votre réponse. Pour répondre à votre interrogation, je compte d'abord récupérer un onglet de mon canvas dans une variable, pour la faire apparaître quand je clique sur une province : !(https://cdn.discordapp.com/attachments/391512242996117505/615180116317962250/Capture_decran_47.png) Les graphismes sont temporaires. Donc, quand je clique sur un fief, l'onglet se met à jour avec les infos de celle-ci, et apparaît. Pour cela, cependant, je dois renseigner manuellement, pour chaque province, ce même onglet. C'est faisable, mais ardu... Pour régler ce problème, j'essaie de récupérer le GameObject de l'onglet via un script. Mais, bien que l'onglet soit actif, je n'y arrive pas...

            -
            Edité par CharlesSAMAMA 25 août 2019 à 19:13:02

            • Partager sur Facebook
            • Partager sur Twitter
              25 août 2019 à 20:08:13

              Donc si je comprend bien, les provinces ont chacunes des valeurs.

              Lorsque l'on clique sur une province elle envoie ses données (variables nom, images etc ...) à l'onglet d'information de province qui s'activera et affichera les informations de la provinces.

              Si j'ai bien compris le problème serait de pouvoir référencer l'onglet d'information (GameObject) lors du click. Il y a pour ce faire plusieurs solutions :

              (J'ai fais les exemples de scripts de mémoire)

              • (solution pas très propre) : Recuperer la reference du Canvas via un tag et recuperer le gameObject en tant qu'enfant : GameObject.FindGameObjectWithTag("Canvas").GetChild(0).gameObject
              • Tagger l'onglet avec un tag ex: OngletInfoProvince et y acceder via: GameObject.FindGameObjectWithTag("OngletInfoProvince")
              • Creer un script qui se situe sur l'onglet et qui gère l'affichage des données et le referencer avec : GameObject.FindObjectOfType<NomDuScript>()
              • Verifier si le nom du GameObject.Find("") est correct en écrivant dans la console tous les noms des enfants du Canvas (peut etre que Unity gere mal les espaces par exemple).

              -
              Edité par coukil 25 août 2019 à 20:10:15

              • Partager sur Facebook
              • Partager sur Twitter
                26 août 2019 à 12:45:48

                On se rapproche! Donc, j'ai créé un tableau contenant les objets qui possèdent le script InfoProvinces, créé pour l'occasion, et l'onglet des infos des provinces est le seul GameObject avec ce script. De fait, cette liste ne possède qu'une valeur, l'onglet des infos. Et ça marche! Problème, j'essaie de récupérer ce pannel dans une variable, pour effectuer des opérations sur l'onglet; et je n'y arrive pas... J'ai utilisé le code "ongletInfosFief = trouverOnglet[0] as GameObject;", où trouverOnglet est le tableau dans lequel est référencé le fameux onglet. et, bien que le tableau contienne effectivement l'onglet, j'en suis sûr, je ne parviens pas à faire en sorte que la variable trouve le pannel en question.

                • Partager sur Facebook
                • Partager sur Twitter
                  27 août 2019 à 3:47:45

                  Pourriez vous envoyer votre code (utilisez la balise </> au dessus du champ de texte du forum pour rendre le code lisible) car bien que j'ai approximativement compris comment il fonctionne, je n'ai que peu d'informations permettant de trouver l'erreur.

                  J'ai tenté de vérifier de mon coté si l'erreur pourrait venir du passage de reference de liste à variable (ce qui est improbable) et cela ne semble pas être le cas :

                  public class TestTruc : MonoBehaviour
                  {
                      //la liste des objet contenant le script
                      private List<GameObject> listAffichage;
                  
                  
                      void Start()
                      {
                          listAffichage = new List<GameObject>();
                  
                          //On ajoute POUR L EXEMPLE le gameObject possédant AffichageUI (Canvas)
                          listAffichage.Add(GameObject.FindObjectOfType<AffichageUI>().gameObject);
                  
                          Test();
                      }
                  
                      
                      private void Test()
                      {
                          //Fonctionne
                          GameObject g = listAffichage[0];
                  
                          //Affiche "Canvas"
                          Debug.Log(g);
                  
                      }
                  
                  }
                  




                  • Partager sur Facebook
                  • Partager sur Twitter
                    27 août 2019 à 9:11:09

                    Je ne joint pas tout le script, pour que cela reste compréhensible : <>

                    public class Clique : MonoBehaviour {

                    public GameObject ongletInfosFief;
                    private Object[] trouverOnglet;
                    
                    
                    // Use this for initialization
                    void Start ()
                    {
                        trouverOnglet = Resources.FindObjectsOfTypeAll(typeof(InfoProvinces));
                        ongletInfosFief = trouverOnglet[0] as GameObject;
                    
                    }
                    

                    -
                    Edité par CharlesSAMAMA 27 août 2019 à 9:11:33

                    • Partager sur Facebook
                    • Partager sur Twitter
                      27 août 2019 à 15:22:37

                      Le problème vient du fait que Resources.FindObjectsOfTypeAll(...) retourne un tableau d'Objet et ce tableau d'Objet n'est pas un tableau de GameObject mais un tableau de InfoProvinces (ou classes qui l'héritent).

                      Donc le cast de trouverOnglet[0] as GameObject ne fonctionne pas car InfoProvinces n'est pas un GameObject.

                      Voici par exemple une solution à votre probleme (remplacer AffichageUI par InfoProvinces) :

                          public GameObject ongletInfosFief;
                          private Object[] trouverAffichage;
                          private List<GameObject> trouverOnglet;
                      
                          // Use this for initialization
                          void Start()
                          {
                      
                              trouverAffichage = Resources.FindObjectsOfTypeAll(typeof(AffichageUI));
                              trouverOnglet = new List<GameObject>();
                      
                              foreach (Object b in trouverAffichage)
                              {
                                  trouverOnglet.Add((b as AffichageUI).gameObject);
                      
                              }
                      
                      
                              ongletInfosFief = trouverOnglet[0];
                              Debug.Log(ongletInfosFief);
                      
                          }


                      Ou alors sans utiliser Resources (donc ne fonctionne pas si les GameObject sont desactivé).

                          public GameObject ongletInfosFief;
                          private AffichageUI[] trouverOnglet;
                      
                      
                          // Use this for initialization
                          void Start()
                          {
                              trouverOnglet = GameObject.FindObjectsOfType<AffichageUI>();
                              ongletInfosFief = trouverOnglet[0].gameObject;
                              Debug.Log(ongletInfosFief);
                          }
                      





                      • Partager sur Facebook
                      • Partager sur Twitter
                        27 août 2019 à 16:05:44

                        o_O Puissiez-vous réussir dans tous vos projets, M/Mme Coukil! M'aider à faire mon programme, quelle bonté! Grâce à vous, ça marche!

                        -
                        Edité par CharlesSAMAMA 27 août 2019 à 16:16:33

                        • Partager sur Facebook
                        • Partager sur Twitter
                          27 août 2019 à 16:09:22

                          J'avais écris entre parenthese : remplacer AffichageUI par InfoProvinces.

                          Pour vérifier votre code, plutot que de creer un projet pour l'occasion, j'ai utilisé un ancien projet de jeux vidéo dont j'avais abandonné le developpement et dont je savais qu'il possédait un script (que j'ai crée) nommé AffichageUI sur le canvas.

                          donc plutot que de creer un autre script InfoProvinces, j'ai considéré AffichageUI en tant que InfoProvinces pour l'exemple.

                          Donc pour votre cas, il suffit juste de remplacer AffichageUI par InfoProvinces.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            27 août 2019 à 16:18:28

                            Victoire! Grâce à votre aide, j'ai finalement réussi! Soyez remercié(e)! J'ai honte d'abuser de votre bonté, mais pourrais-je vous demander comment faire de même pour un sprite contenu dans mes fichiers?.... Si non, ce n'est pas grave, vous m'avez déjà bien aidé!

                            -
                            Edité par CharlesSAMAMA 27 août 2019 à 16:59:07

                            • Partager sur Facebook
                            • Partager sur Twitter
                              27 août 2019 à 18:33:53

                              Si jamais ma réponse ne convient pas, il me faudrait plus d'informations sur comment vous avez mis en place les sprites sur votre projet.

                              Pour récupérer le sprite d'une BD:

                              Mon exemple se base sur un ancien projet où j'avais eu besoin d'afficher les sprites d'un scriptable object pour faire une sorte d'inventaire de blocks (un peu comme Minecraft). Les nom des classes n'ont donc pas de rapport avec votre projet.

                              Il faut que chaque Fief dans la liste présent sur votre ScriptableObject(BD) possède un ID, un identifiant unique. En programmation on utilise généralement des int, mais cela peut aussi être un String. La seule condition est que deux fiefs n'aient pas le même identifiant. Ce qui pose généralement des problemes avec les strings si il existe par exemple deux fiefs s'appelant "France" (même si je doute que cela arrive).

                              Il faut ensuite créer une fonction permettant de récuperer le fief via un identifiant (avec une fonction dans votre BD)

                              Dans mon cas :

                              [CreateAssetMenu(fileName = "BlockDB")]
                              public class BlockScriptable : ScriptableObject//classe de la BD
                              {
                              
                                  public List<BlockData> datas;//pour vous liste des fiefs
                              
                              
                              
                                  public BlockData GetBlockDataById(int id)
                                  {
                                      foreach(BlockData b in datas)
                                      {
                                          if (b.id == id)
                                          {
                                              return b;
                                          }
                                      }
                              
                                      return null;
                              
                              
                                  }
                              }

                              où BlockData(pour vous Fiefs) possède les valeur

                                  public int id;
                                  public string nom;
                                  public Sprite sprite;
                                  public Type type;

                              Vous devez mettre votre BD dans un dossier nommé "Resources" (comme conseillé dans un message ci dessus) pour pouvoir l'appeler et modifier l'image via Resouces.Load.

                              Le code pour pouvoir ensuite assigner une image serait le suivant :

                              /*
                              ATTENTION INSERER : using UnityEngine.UI;
                              Avant la déclaration de la classe (public class ....).
                              */
                              
                              int id = 0;//Pour l'exemple, a vous de trouver comment déterminer l'ID à assigner.(vu que c'est celle du fief à afficher)
                              
                              BlockScriptable bDatabase = (BlockScriptable) Resources.Load("BlockDatabase");
                              
                              BlockData blockData = bDatabase.GetBlockDataById(id);
                              
                              //J'ai ajouté un composant Image sur mon GameObject
                              
                              Image image = GetComponent<Image>();
                              image.sprite = blockData.sprite;


                              Comme mes scripts étaient plus compliqués j'ai regroupé les lignes les plus importantes ci dessus.


                              -
                              Edité par coukil 27 août 2019 à 18:39:08

                              • Partager sur Facebook
                              • Partager sur Twitter
                                28 août 2019 à 14:50:21

                                Je suis navré, mais j'ai beau retourner le problème dans tous les sens, je n'y arrive pas.... Donc, mes fichier PNG sont dans le fichier Resources, tout comme un materiel. J'ai réussi à récupérer le materiel via le script, mais pas les images... Voici les lignes qui influent: <>

                                public Sprite trouverCouronne;
                                public Image trouverImageCouronne;
                                

                                <> if (baronnie)

                                    {
                                        rangFief = "Baronnie";
                                        trouverImageCouronne = (Image) Resources.Load("Baron");
                                        trouverCouronne = trouverImageCouronne.sprite;
                                    }
                                    else if (vicomté)
                                    {
                                        rangFief = "Vicomté";
                                        trouverImageCouronne = (Image)Resources.Load("Comte");
                                        trouverCouronne = trouverImageCouronne.sprite;
                                    }
                                    else if (comté)
                                    {
                                        rangFief = "Comté";
                                        trouverImageCouronne = (Image)Resources.Load("Comte");
                                        trouverCouronne = trouverImageCouronne.sprite;
                                    }
                                    else if (marquisat)
                                    {
                                        rangFief = "Marquisat";
                                        trouverImageCouronne = (Image)Resources.Load("Marquis");
                                        trouverCouronne = trouverImageCouronne.sprite;
                                    }
                                    else if (duché)
                                    {
                                        rangFief = "Duché";
                                        trouverImageCouronne = (Image)Resources.Load("Duc");
                                

                                -
                                Edité par CharlesSAMAMA 28 août 2019 à 14:51:30

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  28 août 2019 à 16:27:57

                                  Ce que je voyais en fait était de mettre une variable public sprite dans Fief. Pas besoin de referencer les image avec Resources.Load.

                                  Voici un par exemple la construction d'un sciptable Object possédant un sprite :

                                  using System.Collections;
                                  using System.Collections.Generic;
                                  using UnityEngine;
                                  
                                  #if UNITY_EDITOR
                                  using UnityEditor;
                                  
                                  [CustomEditor(typeof(FiefBD))]
                                  public class FiefBDEditor : Editor
                                  {
                                      public override void OnInspectorGUI()
                                      {
                                          DrawDefaultInspector();
                                  
                                  
                                          FiefBD myScript = (FiefBD)target;
                                          if (GUILayout.Button("Assigner Id"))
                                          {
                                              for (int i = 0; i < myScript.fiefListe.Count; i++)
                                              {
                                                  myScript.fiefListe[i].id = i;
                                              }
                                  
                                          }
                                  
                                      }
                                  }
                                  #endif
                                  
                                  
                                  
                                  [CreateAssetMenu(fileName = "FiefDatabase")]
                                  public class FiefBD : ScriptableObject
                                  {             //The scriptableObject where the Item getting stored which you create(ItemDatabase)
                                  
                                  
                                      [SerializeField]
                                      public List<Fief> fiefListe;
                                  
                                      public Fief findFiefById(int id)
                                      {
                                  
                                          foreach (Fief f in fiefListe)
                                          {
                                              if (f.id == id)
                                                  return f;
                                  
                                          }
                                          return null;
                                  
                                      }
                                      
                                      
                                               
                                  }
                                  
                                  [System.Serializable]
                                  public class Fief {
                                  
                                      public int id;
                                      public string nom;
                                      public Sprite image;
                                      public string desc;
                                  
                                  
                                  }

                                  J'ai mis une variable public de type Sprite nommé image. Ainsi lorsque lorsque l'on crée la base de donnée, il proposeront de selectionner une image représentant le drapeau/armoiries du fief. Ci dessous on peut voir que qu'ils proposent de referencer une image.

                                  J'ai par exemple importé deux images dans mon projet (et pas besoin de mettre les images dans Resources, seule la base de donnée est à mettre dans Resouces) dont l'une est le drapeau breton et l'autre le drapeau de franche comté. Une fois les image importés, on peut changer leur type en cliquant dessus, selectionnant Sprite et l'on peut comme cela les glisser dans notre liste.

                                  J'ai ensuite crée un script (pour l'exemple) qui vas afficher le Fief suivant l'ID choisis dans l'inspecteur. Il se met sur un composant de type Image.

                                  using System.Collections;
                                  using System.Collections.Generic;
                                  using UnityEngine;
                                  using UnityEngine.UI;
                                  
                                  public class ZoneFief : MonoBehaviour
                                  {
                                  
                                      public int fiefId = 0;
                                      private Image image;
                                  
                                  
                                      private void Start()
                                      {
                                          image = GetComponent<Image>();
                                          FiefBD f = (FiefBD)Resources.Load("FiefDatabase");
                                  
                                          image.sprite = f.fiefListe[fiefId].image;
                                  
                                  
                                      }
                                  
                                  }
                                  



                                  Je n'ai mis dans Resources que une base de donnée crée à partir de mon scriptableObject nommé FiefDatabase (dont les données saisies sont ci dessus). On voit dans l'inspecteur à droite que j'ai choisis l'ID du fief numéro 1, soit le franche comté, il affichera donc sur l'image le drapeau de la franche comté à l'execution.

                                  Ce que j'ai réalisé ne sont que des exemples pour montrer la maniere de coder. Ce n'est donc pas à copier coller mais bien à comprendre.

                                  PS : plutot que d'utiliser les if et else if, autant utiliser un switch :

                                  https://unity3d.com/fr/learn/tutorials/topics/scripting/switch-statements

                                  -
                                  Edité par coukil 28 août 2019 à 16:36:33

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    28 août 2019 à 17:20:36

                                    Je vous remercie pour votre aide! j'ai finalement réussi à venir à bout de ces difficultés! Et pour finir, acceptez-vous que je vous cite, dans le cas, très improbable, où je parvienne à achever le jeu?

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      30 août 2019 à 20:44:11

                                      Pourquoi pas, merci de la proposition :).

                                      Bien que Jean Bom n'est évidemment pas mon vrai nom et que coukil n'est pas un pseudo que j'utilise souvent.

                                      Bonne chance pour votre projet.

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Unity - Problème avec les GameObjects

                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                      • Editeur
                                      • Markdown