quiz & Mail system - T3rabyte/Examen GitHub Wiki

general

The quiz system serves as the foundation for our core game mechanics. We chose to develop a quiz-style game because it offers a straightforward and easily understandable gameplay concept. Despite its simplicity, a quiz game effectively educates the player and tests their knowledge on a specific subject. This aligns perfectly with the objectives of Gemeente Amsterdam (municipality of Amsterdam), as it meets their requirements for an engaging and educational experience.

Quiz system

When I decided to create a quiz-style game, I began my research to find guidance on how to build it. Fortunately, I came across a helpful tutorial that provided me with the necessary framework. This tutorial became a valuable resource as it offered step-by-step instructions, saving me time and effort in figuring out the basics of the game. By following the tutorial, I was able to focus on customizing and expanding the game according to my specific requirements. This simplified the development process and resulted in the creation of an engaging quiz game.

array & list

To implement the quiz system, I created an array to store all the questions available in the game. Additionally, I designed a list specifically for holding unanswered questions, ensuring that duplicates are avoided when selecting questions.

The array contains a comprehensive collection of questions that can be presented to the player during gameplay. On the other hand, the list is responsible for keeping track of questions that have not been answered yet. This prevents repetition and ensures a unique and engaging experience for the player.

By utilizing both the array and the list, we can efficiently manage the selection of questions, track the player's progress, and ensure that each question is presented only once. This approach guarantees variety and avoids redundancy in the quiz, enhancing the overall gameplay experience.

public Question[] questions;
    private static List<Question> unansweredQuestions;

Question, Answer & Explanation Text data

At the beginning of the game, we perform a check to determine whether the list of unanswered questions is empty. If it is empty, we fill it with the contents of the questions array. This ensures that there are available questions for the player to answer. Once this process is completed, we proceed to randomly select a question from the newly populated list.

During the question selection process, we also verify the boolean value of the chosen question to determine if it is true or false. Additionally, we retrieve the corresponding explanation that the game will display if the player answers incorrectly. These elements contribute to providing informative feedback to the player.

Furthermore, we dynamically set the text displayed behind each answer button to indicate whether it is the correct or wrong choice. This allows for clear visual distinction between the options and aids the player in making their selection.

To achieve this functionality, we utilize the content stored in the array within the list, which is obtained from the QuestionData class. The QuestionData class leverages the Questions class and incorporates JSON for efficient data handling. For more detailed information on this implementation, please refer to the Feedback header below.

image

public class QuestionData
    {
        public Question[] questions;
    }

Snippet of the JSON, there is more but this is enough to make it clear what it does

{
	
	"questions": [
		{
		  "fact": "Hackers kunnen toegang krijgen tot uw persoonlijke gegevens door uw wachtwoord te raden.",
		  "isTrue": true,
		  "explanation": "Deze feit is waar omdat hackers toegang kunnen krijgen tot persoonlijke informatie door wachtwoorden te raden vanwege veelvoorkomende kwetsbaarheden. Zwakke wachtwoorden, hergebruik van wachtwoorden voor verschillende accounts, social engineering-tactieken en aanvallen met brute kracht dragen allemaal bij aan het risico."
		},
		{
		  "fact": "Biometrische authenticatie is altijd veiliger dan het gebruik van een wachtwoord.",
		  "isTrue": false,
		  "explanation": "De bewering is niet helemaal waar, want hoewel biometrische authenticatie bepaalde voordelen heeft, is het niet altijd veiliger dan het gebruik van een wachtwoord. Biometrische gegevens kunnen worden gerepliceerd of vervalst, waardoor ze kwetsbaar zijn voor ongeoorloofde toegang. Bovendien, als biometrische gegevens worden gecompromitteerd, kunnen deze niet worden gewijzigd zoals een wachtwoord, wat een veiligheidsrisico op de lange termijn vormt."
		}
	]
}
[System.Serializable]
public class Question
{
    public string fact;
    public bool isTrue;
    public string explanation;
    
}
 if (unansweredQuestions == null || unansweredQuestions.Count == 0)
        {
            unansweredQuestions = questions.ToList<Question>();
        }

SetCurrentQuestion();


void SetCurrentQuestion()
    {
        int randomQuestionIndex = UnityEngine.Random.Range(0, unansweredQuestions.Count-1);
        currentQuestion = unansweredQuestions[randomQuestionIndex];

        

        foreach (Question question in questions)
        {
            string fact = question.fact;
            bool istrue = question.isTrue;

            // Use the values as needed
            // ...
        }
        
        factText.text = currentQuestion.fact;
        explanationText.text = currentQuestion.explanation;

        unansweredQuestions.RemoveAt(randomQuestionIndex);

        if (currentQuestion.isTrue)
        {
            trueAnswerText.text = "CORRECT!";
            falseAnswerText.text = "WRONG!";
            

        }else
        {
            trueAnswerText.text = "WRONG!";
            falseAnswerText.text = "CORRECT!";
            
        }

    }

Answering

To handle the process of answering questions in our game, we utilize the data obtained when a question is selected. This data allows us to determine the correct answer. When the player chooses an answer, we compare it with the correct option and proceed accordingly.

Upon selecting an answer, we activate the corresponding animation, providing immediate visual feedback to the player. This animation reveals whether the chosen answer is correct or incorrect. If the answer is correct, we award the player a point and initiate the transition coroutine, smoothly transitioning to the next question.

However, if the player answers incorrectly, we present a popup that offers an explanation for why the chosen answer was wrong. This popup ensures that the player has a chance to understand the mistake. In this case, we delay moving on to the next question until the player closes the popup. This pause allows the player sufficient time to read and comprehend the explanation provided.

By incorporating these elements into the game mechanics, we enhance the learning experience for the player, providing immediate feedback on their performance while offering educational insights for incorrect answers.

image

public void UserSelectTrue()
    {

        animator.SetTrigger("True");
        if (currentQuestion.isTrue)
        {

            
            correctAnswers += 1;
            Debug.Log("CORRECT!");

            StartCoroutine(TransitionToNextQuestion());
            
        }else
        {
            Debug.Log("WRONG!");

            float random = UnityEngine.Random.Range(0, 1);

            //handles the chance of any effect happening, when entering chances make sure to 
            //keep in mind that popup will only activate if the number is equal to or lower than the given float value
            //freeze effect works the same way except for that the value generated has to be equal to or higher than the given float value
            if(random <= chanceP)
            {
                Popup.SetActive(true);
            }
            
        }

        
    }


    //does the same as above but for "false"
    public void UserSelectFalse()
    {
        animator.SetTrigger("False");
        if (!currentQuestion.isTrue)
        {
            correctAnswers += 1;
            Debug.Log("CORRECT!");

            

            StartCoroutine(TransitionToNextQuestion());
            
        }else
        {
            float random = UnityEngine.Random.Range(0, 1);

            //handles the chance of any effect happening, when entering chances make sure to 
            //keep in mind that popup will only activate if the number is equal to or lower than the given float value
            //freeze effect works the same way except for that the value generated has to be equal to or higher than the given float value
            if(random <= chanceP)
            {
                Popup.SetActive(true);
            }
            

            Debug.Log("WRONG!");

            
        }
        
    }
//gives the program some time to register the next question
    IEnumerator TransitionToNextQuestion()
    {

        yield return new WaitForSeconds(timeBetweenQuestions);

        //SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        SetCurrentQuestion();
    }

Win & Lose

In our game, when the player accumulates enough points by answering questions correctly, we trigger the "win" function. This function activates the "win" game object, which includes a visually appealing background displaying the message "You Win," accompanied by a button allowing the player to return to the main menu.

Similarly, if the player fails to accumulate enough points before the time runs out, we handle the situation in a similar manner. The "lose" function is activated, leading to the display of the "lose" game object, featuring a background that conveys the message "You Lose." Additionally, it includes a button enabling the player to return to the main menu.

These mechanisms provide clear feedback to the player based on their performance, creating a satisfying experience and encouraging them to strive for success in the game.

private void Update()
    {
        //handles the conditions that have to be met to activate a win or a lose
        if (correctAnswers >= 15)
        {
            Win();
            networkVarManager.gameFinished = true;
            networkVarManager.ShowScreenServerRpc();
            
        }
        else if (timer.TimeLeft <= 0f && correctAnswers <= 14)
        {
            Lose();
            networkVarManager.ShowScreenServerRpc();
            
        }
 public void Win()
    {
        win.SetActive(true);
        Debug.Log("gewonnen");
    }

    public void Lose()
    {
        lose.SetActive(true);
    }

polish

To enhance our polish, we made the decision to transition our text data to JSON format. This change offers several benefits, including improved usability and long-term maintenance. By adopting JSON, we empower players to contribute their own questions, fostering a more engaging experience. This idea was inspired by the knowledge I gained during my internship, as well as my personal frustration with the tedious task of manually setting each question in the Unity editor.

 string filePath = Path.Combine(Application.streamingAssetsPath, "JSONText.json");
        if (File.Exists(filePath))
        {
            string data = File.ReadAllText(filePath);
            var questionData = JsonUtility.FromJson<QuestionData>(data);
            questions = questionData.questions;
        }
        else
        {
            Debug.LogError("Questions JSON file not found!");
        }
[System.Serializable]
public class Question
{
    public string fact;
    public bool isTrue;
    public string explanation;
    
}

Here is a snippet of the JSON data, providing a clear understanding of its functionality. Please note that there is more to it, but this excerpt should suffice:

{
	
	"questions": [
		{
		  "fact": "Hackers kunnen toegang krijgen tot uw persoonlijke gegevens door uw wachtwoord te raden.",
		  "isTrue": true,
		  "explanation": "Deze feit is waar omdat hackers toegang kunnen krijgen tot persoonlijke informatie door wachtwoorden te raden vanwege veelvoorkomende kwetsbaarheden. Zwakke wachtwoorden, hergebruik van wachtwoorden voor verschillende accounts, social engineering-tactieken en aanvallen met brute kracht dragen allemaal bij aan het risico."
		},
		{
		  "fact": "Biometrische authenticatie is altijd veiliger dan het gebruik van een wachtwoord.",
		  "isTrue": false,
		  "explanation": "De bewering is niet helemaal waar, want hoewel biometrische authenticatie bepaalde voordelen heeft, is het niet altijd veiliger dan het gebruik van een wachtwoord. Biometrische gegevens kunnen worden gerepliceerd of vervalst, waardoor ze kwetsbaar zijn voor ongeoorloofde toegang. Bovendien, als biometrische gegevens worden gecompromitteerd, kunnen deze niet worden gewijzigd zoals een wachtwoord, wat een veiligheidsrisico op de lange termijn vormt."
		}
	]
}

This snippet showcases the structure of the JSON data, featuring multiple questions with their respective IDs, texts, answer options, and correct options. It provides a foundation for a more comprehensive JSON file, facilitating the implementation and customization of questions within the game.

⚠️ **GitHub.com Fallback** ⚠️