Supprimer le double click sur les boutons

Questions à propos du GUI, y compris la partie script.
abbadon93
Messages : 11
Inscription : 07 Mai 2020 11:57

Supprimer le double click sur les boutons

Message par abbadon93 » 16 Mai 2020 16:27

Bonjour.

Je suis en train de développer un logiciel éducatif de style QCM. En UI, j'affiche des boutons pour que les utilisateurs puissent répondre. Le problème, c'est qu'ils peuvent cliquer rapidement une dizaine de fois lors de la question 1 et cela rempli automatiquement les autres questions.

J'ai fait des recherches et j'ai trouvé une solution. J'ai désactivé les boutons après le premier click et demandé de les réactiver en lançant la question suivante. Le problème, c'est que lors de la désactivation, ça a bloqué le programme.

Vous pouvez trouver en dessous le script fonctionnel.

Si en plus je peux avoir des conseils pour améliorer le script, ça serait génial.
Un point important, je suis un très grand novice en Unity, alors ne soyez pas surpris du code de cochon, je me suis servi de ce que j'ai pu trouver à droite et à gauche.

Merci pour votre aide.

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class modA01 : MonoBehaviour
{
//  nb de boutons 
    private Text txtQuestion0;
    private Text txtQuestion1;
    private Text txtQuestion2;
    private Text txtQuestion3;
    private Text txtQuestion4;
    private Text txtScore;
    private TextMesh txtBtn1;
    private TextMesh txtBtn2;
    private TextMesh txtBtn3;
    private TextMesh txtBtn4;
    private TextMesh txtBtn5;
    private TextMesh txtBtn6;
    private TextMesh txtBtn7;
    private TextMesh txtBtn8;
    private TextMesh txtBtn9;
    private TextMesh txtBtn10;

    private int nombrerandom; // nombre aléatoire
    private int nombrei = 0;

    public string reponse;
    public int score = 0;
    private int totalQuestion = 12; // nombre de question par qcm
    private int nbQuestion = 0; // nombre de questions posées

    private int tmpi = 0; // initialisation du compteur tmpi

    // Déclaration du tableau
    string[] Quizz = new string[12]; // nb de questions dans tableau

    // Start is called before the first frame update
    void Start()
    {

        // Composants
        txtQuestion0 = GameObject.Find("TxtQuestion0").GetComponent<Text>();
        txtQuestion1 = GameObject.Find("TxtQuestion1").GetComponent<Text>();
        txtQuestion2 = GameObject.Find("TxtQuestion2").GetComponent<Text>();
        txtQuestion3 = GameObject.Find("TxtQuestion3").GetComponent<Text>();
        txtQuestion4 = GameObject.Find("TxtQuestion4").GetComponent<Text>();
        txtScore = GameObject.Find("TxtScore").GetComponent<Text>();
        txtBtn1 = GameObject.Find("Txt1").GetComponent<TextMesh>();
        txtBtn2 = GameObject.Find("Txt2").GetComponent<TextMesh>();
        txtBtn3 = GameObject.Find("Txt3").GetComponent<TextMesh>();
        txtBtn4 = GameObject.Find("Txt4").GetComponent<TextMesh>();
        txtBtn5 = GameObject.Find("Txt5").GetComponent<TextMesh>();
        txtBtn6 = GameObject.Find("Txt6").GetComponent<TextMesh>();
        txtBtn7 = GameObject.Find("Txt7").GetComponent<TextMesh>();
        txtBtn8 = GameObject.Find("Txt8").GetComponent<TextMesh>();
        txtBtn9 = GameObject.Find("Txt9").GetComponent<TextMesh>();
        txtBtn10 = GameObject.Find("Txt10").GetComponent<TextMesh>();

        // Déclaration du contenu du tableau
        Quizz[0] = "1;+;1;=;?;0;1;2;3;4;5;6;7;8;9;2";
        Quizz[1] = "1;+;2;=;?;0;1;2;3;4;5;6;7;8;9;3";
        Quizz[2] = "1;+;3;=;?;0;1;2;3;4;5;6;7;8;9;4";
        Quizz[3] = "1;+;4;=;?;0;1;2;3;4;5;6;7;8;9;5";
        Quizz[4] = "5;+;1;=;?;0;1;2;3;4;5;6;7;8;9;6";
        Quizz[5] = "3;+;1;=;?;0;1;2;3;4;5;6;7;8;9;4";
        Quizz[6] = "4;+;1;=;?;0;1;2;3;4;5;6;7;8;9;5";
        Quizz[7] = "2;+;1;=;?;0;1;2;3;4;5;6;7;8;9;3";
        Quizz[8] = "3;+;?;=;4;0;1;2;3;4;5;6;7;8;9;1";
        Quizz[9] = "5;+;1;=;?;0;1;2;3;4;5;6;7;8;9;6";
        Quizz[10] = "2;+;3;=;?;0;1;2;3;4;5;6;7;8;9;5";
        Quizz[11] = "2;+;2;=;?;0;1;2;3;4;5;6;7;8;9;4";

        PoseUneQuestion();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void PoseUneQuestion()
    {
        txtScore.text = "Score : " + score;

        if (nbQuestion < totalQuestion)
        {
            nbQuestion += 1;
            // Questions en mode aléatoire
            //    nombrerandom = Random.Range(0, Quizz.Length);
            //    string[] Col = Quizz[nombrerandom].Split(';');

            // tableau boutons
            string[] Col = Quizz[nombrei].Split(';');
            txtQuestion0.text = Col[0];
            txtQuestion1.text = Col[1];
            txtQuestion2.text = Col[2];
            txtQuestion3.text = Col[3];
            txtQuestion4.text = Col[4];
            txtBtn1.text = Col[5];
            txtBtn2.text = Col[6];
            txtBtn3.text = Col[7];
            txtBtn4.text = Col[8];
            txtBtn5.text = Col[9];
            txtBtn6.text = Col[10];
            txtBtn7.text = Col[11];
            txtBtn8.text = Col[12];
            txtBtn9.text = Col[13];
            txtBtn10.text = Col[14];
            reponse = Col[15];

            PlayerPrefs.SetInt("tmpi", nombrei);
            nombrei += 1;
        }
        else
        {
            // sauvegarde du score

            PlayerPrefs.SetInt("scoreA01", score);
            PlayerPrefs.Save();
            // Debug.Log("Partie terminée, score de " + Score + "/" + totalQuestion);
            SceneManager.LoadScene("modules");
        }
    }

    void OnMouseDown()
    {

        // module 1

        if (GameObject.Find("Canvas").GetComponent<modA01>().reponse == transform.GetChild(0).GetComponent<TextMesh>().text)
        {

            // Debug.Log("Gagné !");
            int tmpi = PlayerPrefs.GetInt("tmpi");
            // Debug.Log("gagner : tmpi = " + tmpi);

            // module 2

            GameObject.Find("Canvas").GetComponent<modA01>().score += 1;

            // tmpi1 - exception pour format du qcm (ex 1+?=3 au lieu de 1+2=?)

            if (tmpi == 8)
            {
                txtQuestion2.color = Color.green;

                // module 3

                txtQuestion2.text = GameObject.Find("Canvas").GetComponent<modA01>().reponse;
            }
            else
            {
                txtQuestion4.color = Color.green;

                // module 4

                txtQuestion4.text = GameObject.Find("Canvas").GetComponent<modA01>().reponse;
            }
        }
        else
        {

            // Debug.Log("Perdu !");
            int tmpi = PlayerPrefs.GetInt("tmpi");
            // Debug.Log("perdre : tmpi = " + tmpi);

            // tmpi2

            if (tmpi == 8)
            {
                txtQuestion2.color = Color.red;
                txtQuestion2.text = transform.GetChild(0).GetComponent<TextMesh>().text;
            }
            else
            {
                txtQuestion4.color = Color.red;
                txtQuestion4.text = transform.GetChild(0).GetComponent<TextMesh>().text;
            }

        }

        StartCoroutine(MyCoroutine());

        IEnumerator MyCoroutine()
        {
            yield return new WaitForSeconds(2);

            txtQuestion0.color = Color.black;
            txtQuestion2.color = Color.black;
            txtQuestion4.color = Color.black;

            // module 5

            GameObject.Find("Canvas").GetComponent<modA01>().PoseUneQuestion();

        }
    }
}

EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Re: Supprimer le double click sur les boutons

Message par EmileF » 16 Mai 2020 18:16

Salut,

Je n'ai pas tout compris dans ton script, mais j'ai remarqué quelque chose qui ne me plait pas, je me trompe peut-être.

Mais ta coroutine "MyCoroutine" est située dans la méthode "OnMouseDown", et je crois que c'est là ton erreur.

Fais un essai en sortant cette coroutine de OnMouseDown.
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

abbadon93
Messages : 11
Inscription : 07 Mai 2020 11:57

Re: Supprimer le double click sur les boutons

Message par abbadon93 » 17 Mai 2020 09:49

Merci pour le bug.

Code : Tout sélectionner

public GameObject[] objs;

Code : Tout sélectionner

        objs = GameObject.FindGameObjectsWithTag("Tagada");
        foreach (GameObject button in objs)
        {
            button.GetComponent<Button>().interactable = false;
        }
Voici l'élément que j'essaye d'intégrer après le "OnMouseDown" pour empêcher que les personnes cliquent une tonne de fois quand juste une est nécessaire avec l'objectif de mettre dans "MyCoroutine" la valeur à "true" pour le réactiver à la question suivante.

Bon, ça ne fonctionne pas.

Hmmm, Tagada étant le tag donné aux boutons.

Si vous avez de quoi m'éclairer, je suis preneur.

Bon week-end.

djulio74
Messages : 682
Inscription : 19 Déc 2009 22:55

Re: Supprimer le double click sur les boutons

Message par djulio74 » 17 Mai 2020 10:16

Je suis pas non plus sur d'avoir bien comprise le fonctionnement que tu veux atteindre.
Ma vision :
Un qcm est une suite de question à choix multiple, avec un temps impartis ou non pour chaque question.
Que ce soit avec temps impartis ou non, le joueur oit pouvoir changer de réponse tant que la question est affichée. Il ne faut donc pas compter le nombre de clique pour assigner les réponse les unes après les autre, mais tant que tu est sur une question, chaque clique change la réponse à cette question.
Dans le principe tu arrais :
- un array de question
- un array de int réponse, du même nombre d'élément que les questions.que tu replira à chaque question
- un int Question : serait l'index de la question en cours dans ton array de question

pour chaque question, quand tu clique sur une des réponse, ça assigne la réponse à la question affichée. En pseudo code ça donnerais :

Code : Tout sélectionner

string[] question = new string[10]; // disons 10 questions
int[] répone = new int[10]; // stock la réponse pour chaque question
int QestionEnCours;

void PoserQuestion(QuestionEnCours){

	if (JeCliqueSurUneRéponse){
		reponse[QuestionEnCours] = reponse.Cliquée
	}
	if(TempsRestant == 0 ou JeCliqueSurQuestionSuivante){
		QuestionEnCours +=1;
	}
}
Ce serait a peu près un principe de fonctionnement simple et fonctionnel.
Si tu n'y arrive pas, je tenterai de le faire plus en rapport avec ton script a toi.

______________________________________________________________
\_______________________ Impossible is nothing _______________________/

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

Re: Supprimer le double click sur les boutons

Message par jmhoubre » 17 Mai 2020 12:14

Les commentaires
Déjà, il y a des commentaires, c'est bien. En revanche :
- private int nombrerandom; // nombre aléatoire est inutile, car la variable est pafaitement nommée. idem pour // initialisation du compteur tmpi et // Déclaration du tableau. Les commentaires inutiles alourdissent la lecture en fournissant des informations peu utiles.
- le premier commentaire, // nb de boutons, est mal choisi : suivant en effet des déclarations de champs divers et variés, mais pas un seul nombre.
- idem pour string[] Quizz = new string[12]; // nb de questions dans tableau

Le nom des variables
Je ne suis pas contre le métissage, mais pour les variables, le mélange français anglais est un peu pénible. L'habitude est d'utiliser l'anglais, plus compact, mais le français peut également convenir.
Il est important de suivre les conventions usuelles, en particulier la casse. On utilise camelCase pour une variable et PascalCase pour le reste (en gros). Donc pour une variable, le premier mot est en minuscule, et les suivants en majuscules. Cela améliore la lisibilité.
- ainsi nombrerandom pourrait s'écrire randomNumber, ou nombreAleatoire.
- Quizz devrait être renommé en quizz, ou peut-être, en tableauQuestions.Le nom des variables doit être signifiant, c'est-à-dire indiquer clairement à quoi elles servent (ceci ne concerne pas les i, j, k et autres x des compteurs de boucles^^). Cela évite de mettre un commentaire, qui ne sera de toute manière présent qu'à un endroit.
- nombrei est un très mauvais nom. J'ai l'impression que tu as laissé tomber le choix aléatoire d'une question, pour les poser toutes. Du coup la fonction porte très mal son nom. Je te proposerai d'utiliser ceci :

Code : Tout sélectionner

public bool PoserLaQuestion(int numeroQuestion) {
	// Teste la validité de la question.
	if (numeroQuestion > totalQuestion) {
		return false;
	} else {
		// Ton code, qui doit renvoyer true, si tout s'est bien passé.
	}
}   
Poser une question sur le forum
Il faut pas mal de temps pour arriver à comprendre la façon dont tu te sers de ton QCM. Une petite explication aurait été sympathique, avec par exemple le lien vers le tuto.
"Je me sers d'un tableau tableauQuestions, etc..."
J'ai passé trop de temps à comprendre Quizz[0] = "1;+;1;=;?;0;1;2;3;4;5;6;7;8;9;2";, qui me parait d'emblée comme une source au mieux d'incompréhensions, au pire d'erreurs.

Divers
Autre chose : la fonction Update () est vide, pourquoi la laisser quand tu poses la question sur le forum ? Le code est déjà long, et les possibilités d'affichage sont limitées, obligeant à de fréquents allers retours.

Tu utilises des Find un peu partout, mauvaise habitude. Celui dans la fonction OnMouseDown doit être mis en cache !

Code : Tout sélectionner

// Dans la partie déclaration.
	private Canvas canvas;
	
	// Dans le Start.
	private void Start () {
		canvas = GameObject.Find("Canvas");
	}
	
	// Dans OnMouseDown.
	if (canvas.GetComponent<modA01>().reponse == transform.GetChild(0).GetComponent<TextMesh>().text)
Pourquoi tu n'utilises pas de vrais boutons d'UI ?
Bon, c'est l'heure de manger, j'essaierais de continuer plus tard.

abbadon93
Messages : 11
Inscription : 07 Mai 2020 11:57

Re: Supprimer le double click sur les boutons

Message par abbadon93 » 18 Mai 2020 11:32

Bonjour,

djulio74 et jmhoubre, merci pour vos réponses.

Par contre, vous m'avez déjà largué, désolé.


A l'origine, j'ai trouvé un script de quiz sur Youtube, je l'ai récupéré et aménagé pour faire le QCM. Je pense qu'il était peut être pas déjà optimal et en rajoutant ma sauce, ça n'a pas arrangé les choses sauf que ça fonctionne.

Code : Tout sélectionner

Quizz[0] = "1;+;1;=;?;0;1;2;3;4;5;6;7;8;9;2";
A l'origine, le 1+1=? n'était pas découpé mais pour changer de place le ? et colorier le résultat selon qu'il est bon ou mauvais, j'ai séparé chaque élément. Ensuite de 0 à 9 viennent les réponses possibles (plus loin, dans d'autres QCM, ça va de 0 à 19) et le dernier chiffre est la réponse.

Quand la personne clique sur un des chiffres (assigné à un bouton), le click est comparé à la réponse et si c'est bon, un point de plus au score, sinon, 0.

djulio74, je reconnais qu'il n'est pas prévu de changer sa réponse. Le premier click est la réponse. Et comme je précise plus tôt, les clicks sont conservés si une personne appuie plusieurs fois. C'est problématique car c'est assigné aux questions suivantes.


jmhoubre, c'est vrai que j'aurais pu supprimer le private int nombre random, ça vient de l'ancien quiz.

Pour le compte tmpi, c'est une chose que j'ai mis en place pour savoir à tout moment à quelle question je me trouve... je n'arrivais pas à récupérer l'information autrement. :(

Beaucoup de commentaires servent surement à rien, mais à mon niveau, ultra débutant, ça permet de me repérer sur le temps et savoir ce que je fais ici ou là.

Pour le nom des variables, je reconnais. Partout dans ce que j'ai pu voir, ils disent qu'il y a des conventions à respecter et ... bon.

Oui, tu as raison, le quiz de base était avec des questions au hasard et je l'ai changé pour faire une suite de questions.

Ce ne sont pas des boutons UI que j'utilise ?


Désolé pour le code ultra mal fait.



Pour le remplacement du Find dans OnMouseDown, il me met en rouge la partie GameObject.Find("Canvas") et m'indique qu'il est impossible de convertir UnityEngine.GameObject en UnityEngine.Canvas. :(

Pour le passage en bool de PoserLaQuestion, ça fonctionne sauf que lorsque la variable numeroQuestion est supérieure à TotalQuestion, là, il n'execute pas la sauvegarde du score et le renvoie vers l'élément "module". :( :(
IndexOutOfRangeException: Index was outside the bounds of the array.



Merci pour votre aide.

Répondre

Revenir vers « L'interface GUI »