[C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Questions à propos du GUI, y compris la partie script.
Répondre
Avatar de l’utilisateur
Murdeau
Messages : 12
Inscription : 30 Juil 2020 14:03
Localisation : Grenoble

[C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par Murdeau » 04 Nov 2020 15:09

Bonjour,
Je fais un jeu qui utilise une soixantaine de scènes différentes.
J'ai donc une soixantaine de boutons à l'écran.
Pour l'instant je n'en ai fait que 10 qui fonctionnent:

Code : Tout sélectionner

    public void bouton1()
    {
               SceneManager.LoadScene("Scene1");
    }
    public void bouton2()
    {
               SceneManager.LoadScene("Scene2");
    }
    public void bouton3()
    {
               SceneManager.LoadScene("Scene3");
    }
    /* ...*/
et pour le premier bouton dans ma hierarchy, j'ai indiqué dans on clic() d'aller faire la fonction bouton1(),
pour le deuxième bouton dans ma hierarchy, j'ai indiqué dans on clic() d'aller faire la fonction bouton2(),
pour le troisième bouton dans ma hierarchy, j'ai indiqué dans on clic() d'aller faire la fonction bouton3()...

bref ce n'est pas de la programmation, c'est très répétitif et long.

Je voudrais savoir quelle est la commande qui permet de connaître un bouton cliqué afin de faire une boucle pour lire tous les boutons et une fois trouvé celui qui a été cliqué, lui faire faire:
SceneManager.LoadScene("Scenei")

Je vous remercie.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5505
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par boubouk50 » 04 Nov 2020 16:03

Nope. Nope Nope Nope. NOOOOOPE !!

Tu ne vas pas t'en sortir comme cela. Il te faut factoriser comme une formule mathématique.

Tu peux déjà créer tes strings en code en concaténant une string et un entier.
Par exemple:

Code : Tout sélectionner

string nomDeScene = "Scene" + count;
//nomDeScene vaut "Scene1" si count == 1, "Scene2" si count == 2, etc 
Ensuite, tu peux affecter une fonction à un bouton (sur le OnClick) grâce à AddListener ().
Donc, si tu vois où je veux en venir, tu peux créer une boucle qui va définir le nom de la scène et affecter une action avec le bon nom de scène à chaque bouton.
Tu peux encore aller plus loin, en créant un prefab du bouton. Et donc dans la boucle, tu instancies un bouton, lui affecte son action et vient le placer dans la scène.
Au final, tu pourrais juste définir le nombre de boutons, et le programme s'occuperait du reste.

Mais faire un à un à la main, c'est non. T'aider dans cette voie, n'est pas une aide. Ce serait comme apprendre à un enfant à ne pas marcher sur des mines, alors qu'il suffirait de toutes les enlever ou de le faire jouer sur un terrain non-miné.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
Murdeau
Messages : 12
Inscription : 30 Juil 2020 14:03
Localisation : Grenoble

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par Murdeau » 04 Nov 2020 19:33

Bonjour,

j'ai essayé d'instancier tous mes boutons (enfin, seulement 10):

Code : Tout sélectionner

public class ScriptButton : MonoBehaviour
{
    public Button ButtonLecon;

    void Start()
    {
        ButtonLecon = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons/ButtonLecon01").GetComponent<Button>();

        Debug.Log("ButtonLecon= " + ButtonLecon);
        for (int i=0; i<10; i++)
        {
            Instantiate<Button>(ButtonLecon, new Vector3(ButtonLecon.transform.position.x, ButtonLecon.transform.position.y + i * 5f,0), Quaternion.identity);
        }
 
    }

ils apparaissent bien dans hierarchy, tout au début mais je n'arrive pas à les mettre enfants du même parent que mon bouton original.
j'ai essayé :

Code : Tout sélectionner

public class ScriptButton : MonoBehaviour
{
    public Button ButtonLecon;
    public GameObject parentButton;

    void Start()
    {
        parentButton = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons");
        ButtonLecon = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons/ButtonLecon01").GetComponent<Button>();

        Debug.Log("ButtonLecon= " + ButtonLecon);
        for (int i=0; i<3; i++)
        {
            Instantiate<Button>(ButtonLecon, Transform parentButton);
        }
 
    }


comme indiqué dans Unity/ Documentation- Scripting API (public static Object Instantiate(Object original, Transform parent);) mais j'ai une erreur: Transform parentButton est souligné en rouge.

Quelle est mon erreur, quelle est la solution ?
Merci

Avatar de l’utilisateur
Murdeau
Messages : 12
Inscription : 30 Juil 2020 14:03
Localisation : Grenoble

Re: [DB-AL] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par Murdeau » 07 Nov 2020 21:02

j'ai trouvé comment mettre mes boutons enfants du parent de mon original:

Code : Tout sélectionner

public class ScriptButton : MonoBehaviour
{
    public Button ButtonLecon, ButtonSuiv;
    public Transform ParentButton;

    void Start()
    {
        ButtonLecon = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons/ButtonLecon01").GetComponent<Button>();
        ParentButton = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons").GetComponent<Transform>();
        for (int i=0; i<10; i++)
        {
            ButtonSuiv = Instantiate<Button>(ButtonLecon, new Vector3(ButtonLecon.transform.position.x, ButtonLecon.transform.position.y + i * -80f,0), Quaternion.identity);
            ButtonSuiv.transform.SetParent(ParentButton);
            ButtonSuiv.name = "ButtonLecon" + i;
        }
 
    }
mais maintenant j'ai un autre problème, je ne comprends pas pourquoi le scale des mes boutons ont diminué ainsi que le -80f.

Avatar de l’utilisateur
Max
Newser
Newser
Messages : 8064
Inscription : 30 Juil 2011 13:57
Contact :

Re: [DB-AL] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par Max » 07 Nov 2020 21:32

Bonsoir,
Murdeau a écrit :
07 Nov 2020 21:02
mais maintenant j'ai un autre problème, je ne comprends pas pourquoi le scale des mes boutons ont diminué ainsi que le -80f.
C'est que leur parent n'a certainement pas un scale égale à 1 j’imagine....
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

Avatar de l’utilisateur
Murdeau
Messages : 12
Inscription : 30 Juil 2020 14:03
Localisation : Grenoble

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par Murdeau » 08 Nov 2020 07:52

boubouk50 a écrit :
04 Nov 2020 16:03
Tu peux encore aller plus loin, en créant un prefab du bouton. Et donc dans la boucle, tu instancies un bouton, lui affecte son action et vient le placer dans la scène.
Au final, tu pourrais juste définir le nombre de boutons, et le programme s'occuperait du reste.
J'ai essayé d'aller encore plus loin comme tu me le conseilles, boubouk50. J'ai donc instancié mes boutons. Cela fonctionne, je suis super fière de moi :vivemoi: mais ils sont tous identiques, ce qui est normal :hehe:

Donc je me suis lancée, pour commencer, dans le changement de l'image qui accompagne chaque bouton.
J'ai créé des préfabs de mes images, je les ai placé dans un tableau mais maintenant je n'arrive pas à changer l'image de la copie par l'image du tableau. Je ne trouve pas l'instruction qui fait ça :pleur4: .

Code : Tout sélectionner

public class ScriptButton : MonoBehaviour
{
    public Button ButtonLecon, ButtonSuiv;
    public Transform ParentButton;
    public GameObject remplaceImage;
    [SerializeField] string[] donneesButton = new string[59];
    public GameObject[] tableauImages;  		//rempli dans hierarchy en déplaçant les préfabs dans le tableau
    private string saveSeparator = "%virgule%";

    void Start()
    {
        remplaceImage = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons/ButtonLecon/centre");  //récupère le gameObjet centre (qui est mon image à changer par la suite) dans hierarchy
        ButtonLecon = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons/ButtonLecon").GetComponent<Button>();  //récupère le gameObjet ButtonLecon dans hierarchy
        ParentButton = GameObject.Find("/Canvas/TitreApprentissage/PanelScrollView/Lecons").GetComponent<Transform>();          //récupère le transform du gameObjet Lecon dans hierarchy
              //pour créer les 58 boutons
        for (int i=1; i<59; i++)
        {
            ButtonSuiv = Instantiate<Button>(ButtonLecon, new Vector3(ButtonLecon.transform.position.x, ButtonLecon.transform.position.y + i * -80f,0), Quaternion.identity);
            ButtonSuiv.transform.GetChild(1).gameObject = tableauImages[i-1]; //C'EST LÀ QUE ÇA MARCHE PAS, L'INSTRUCTION N'EST PAS LA BONNE
            ButtonSuiv.transform.SetParent(ParentButton);
            ButtonSuiv.name = "ButtonLecon" + i;

        }
 
    }
}
merci pour votre aide :reconfort: .

Avatar de l’utilisateur
jmhoubre
Messages : 323
Inscription : 05 Oct 2019 22:05

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par jmhoubre » 08 Nov 2020 14:43

Bonjour,

une remarque à propos du parentage de tes boutons : exécuter SetParent après 'instanciation n'est pas une bonne pratique. Bon là il n'y a que 10 boutons et c'est sur un PC. Le plus efficace c'est de le faire à l'instanciation :

Code : Tout sélectionner

ButtonSuiv = Instantiate<Button>(ButtonLecon, new Vector3(ButtonLecon.transform.position.x, ButtonLecon.transform.position.y + i * -80f,0), Quaternion.identity, ParentButton);
Note : en relisant tout le fil, j'ai vu que tu étais sur la bonne voie, mais tu as écris :

Code : Tout sélectionner

Instantiate<Button>(ButtonLecon, Transform parentButton);
Dans la documentation, une fonction est indiquée avec le type de ses paramètres. Pourtant, tu n'as pas écrit Object ButtonLecon.

Un conseil, comme tu as l'air de débuter, c'est rendre ton code lisible, pour les autres bien sûr, mais surtout pour toi (certains auteurs estiment qu'on passe 90% de son temps à lire son code et 10% à l'écrire). Par exemple, il est plus lisible d'écrire :

Code : Tout sélectionner

Vector3 position = new Vector3 (ButtonLecon.transform.position.x, ButtonLecon.transform.position.y + i * -80f, 0f);
ButtonSuiv = Instantiate<Button>(ButtonLecon, position, Quaternion.identity, ParentButton);
Dernière édition par jmhoubre le 08 Nov 2020 15:10, édité 6 fois.

Avatar de l’utilisateur
jmhoubre
Messages : 323
Inscription : 05 Oct 2019 22:05

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par jmhoubre » 08 Nov 2020 14:55

Pour le scale qui varie, c'est ce que répond Max : le transform d'un enfant est relatif au transform du parent.
Par exemple :

Position du parent : (1, 1, 1)
Position de futurEnfant : (2, 1, -1)
Une fois parenté, position du futurEnfant : (1, 0, -2)

Pour le scale, c'est pratiquement pareil, sauf qu'on divise:
Scale du parent : (4, 1, 0.5)
Scale du futurEnfant (1, 1, 1)
Scale enfant après parentage : (0.25, 1, 2).
Le scale de l'enfant après parentage vaut, pour chaque coordonnée, scale.futurEnfant / scale.parent.
Note : si un des éléments de scale.parent est nul, l'élément correspondant de l'enfant devient nul au parentage.

Avatar de l’utilisateur
jmhoubre
Messages : 323
Inscription : 05 Oct 2019 22:05

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par jmhoubre » 08 Nov 2020 15:17

Pour les images, je suppose que tu parles de l'image de fond des boutons ? Celle qui se trouve dans le champ SourceImage du composant image ? Parce que ton code peut laisser penser que chaque bouton a un enfant (ton GameObject image).

Avatar de l’utilisateur
jmhoubre
Messages : 323
Inscription : 05 Oct 2019 22:05

Re: [C#--DB] Comment savoir si un button a été cliqué sans utiliser on clic()

Message par jmhoubre » 11 Nov 2020 13:14

Bonjour,
en supposant qu'il faut changer l'image de fond du bouton, j'ai fait ceci : Boutons dynamiques

Merci à Boubouk qui m'a permis de déboucher sur l'ajout d'un listener avec paramètre.

Le plus pénible, c'est de calculer l'emplacement des boutons. Il serait plus aisé d'utiliser les layouts.

Code : Tout sélectionner

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;

public class SceneLoader : MonoBehaviour
{
	[SerializeField] private Canvas canvas = null;
	[SerializeField] private GameObject button = null;
	[SerializeField] private Sprite [] buttonImages = null;

	private int scenesToLoad;
	
	private void Start ()
	{
		if (canvas == null)
		{
			Debug.Log ("Canvas absent.");
			return;
		}

		// Nombre de scènes dans les Build settings, moins la scène principale.
		scenesToLoad = SceneManager.sceneCountInBuildSettings - 1;

		CreateButtons ();
	}

	private void CreateButtons ()
	{
		GameObject go;
		float posX = 0f, posY = 0f;
		int col = 0, row = 0;

		// L'origine du bouton est le point de pivot du prefab.
		// Il faut le modifier dans le prefab / RectTransform, et le mettre à (0,0).
		// J'ai choisi de mettre les boutons en haut du canvas.

		// Largeur et hauteur du canvas.
		RectTransform rectTransform = canvas.GetComponent<RectTransform> ();
		float canvasWidth = rectTransform.rect.width;
		float canvasHeight = rectTransform.rect.height;
		// Largeur et hauteur du bouton.
		rectTransform = button.GetComponent<RectTransform> ();
		float buttonWidth = rectTransform.rect.width;
		float buttonHeight = rectTransform.rect.height;
		// Marges du l'ensemble des boutons, à choisir.
		float topMargin = 20f;
		float leftMargin = 15f;
		// Marges de chaque bouton. Pour alléger le code, elles servent de marge droite et de marge basse.
		float buttonTopMargin = 10f;
		float buttonLeftMargin = 5f;

		Debug.Log ($"Largeur canvas : {canvasWidth} - Hauteur canvas : {canvasHeight}");
		Debug.Log ($"Largeur bouton : {buttonWidth} - Hauteur bouton : {buttonHeight}");

		for (int i = 0; i < scenesToLoad; i++)
		{
			// Calcule la position du bouton dans le Canvas. 			
			posX = leftMargin + (col * ((2 * buttonLeftMargin) + buttonWidth));
			Debug.Log ($"posX : {posX} = {leftMargin} + {col} * (2 * {buttonLeftMargin} + {buttonWidth})");
			col++;

			// Le bouton dépasse-t-il du canvas ?
			if (posX + buttonLeftMargin + buttonWidth >= canvasWidth)
			{
				posX = leftMargin;
				Debug.Log ("Ca dépasse -> {posX}");
				col = 1;
				row++;
			}

			// Le pivot est en bas : on enlève la hauteur du bouton.
			posY = canvasHeight - buttonHeight - topMargin - (row * ((2 * buttonTopMargin) + buttonHeight));
			Debug.Log ($"posY : {posY} = {canvasHeight / 2} - {topMargin} - {row} * (2 * {buttonTopMargin} + {buttonHeight})");

			Vector2 position = new Vector2 (posX, posY);

			// Creation du bouton.
			go = Instantiate (button, position, Quaternion.identity, canvas.transform);
			go.name = "Bouton " + (i + 1).ToString ();
			go.transform.GetChild (0).GetComponent<TMP_Text> ().text = "Scène " + (i + 1).ToString ();
			// Ajoute la fonction de chargement de scène.	
			string sceneNameToLoad = "Scene" + (i + 1).ToString ();
			go.GetComponent<Button> ().onClick.AddListener (delegate { LoadMyScene (sceneNameToLoad); });
			// Modifie l'image.
			go.transform.GetComponent<Image> ().sprite = buttonImages [i];
		}
	}

	private void LoadMyScene (string sceneName)
	{				
		SceneManager.LoadScene (sceneName);
	}
}


Répondre

Revenir vers « L'interface GUI »