The question is answered, right answer was accepted
Destroy question if its already asked
Hello Everyone, I made a Quiz Game thanks to the Unity Tutorial https://www.youtube.com/watch?v=hLNPjIxf0C8.
Now I have put this code 'int questionIndex = Random.Range(0, questionPool.Length -1);' in the script under 'private void ShowQuestion()'
To pick up random questions, it works. But its take the same questions that is just asked. I want it to go like question is asked and don't come back in the round and go on with the new questions I am 3 days trying to fix this problem but nothing. I hope you guys can help me out.
Here is the script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Linq;
public class GameController : MonoBehaviour
{
public int playerHealth = 30;
int damage = 10;
public Scrollbar HealthBar;
public float Health = 30;
public AudioClip Goed;
public AudioClip Fout;
public AudioClip klikklak;
public Text TotalscoreDisplayText;
public Text questionDisplayText;
public Text scoreDisplayText;
public Text timeRemainingDisplayText;
public SimpleObjectPool answerButtonObjectPool;
public Transform answerButtonParent;
public GameObject questionDisplay;
public GameObject roundEndDisplay;
public Text HighScoreText;
AudioSource GOED;
AudioSource FOUT;
AudioSource KlikKlak;
private DataController dataController;
private RoundData currentRoundData;
private QuestionData[] questionPool;
private bool[] alreadyAskedQuestions;
private bool isRoundActive;
private float timeRemaining;
private int questionIndex;
private int playerScore;
private List<GameObject> answerButtonGameObjects = new List<GameObject>();
void Awake()
{
GOED = GetComponent<AudioSource>();
FOUT = GetComponent<AudioSource>();
KlikKlak = GetComponent<AudioSource>();
}
// Use this for initialization
void Start()
{
dataController = FindObjectOfType<DataController>();
currentRoundData = dataController.GetCurrentRoundData();
questionPool = currentRoundData.questions;
UpdateTimeRemainingDisplay();
playerScore = 0;
questionIndex = 0;
ShowQuestion();
isRoundActive = true;
HighScoreText.text = " " + ((int)PlayerPrefs.GetFloat("HighScore")).ToString();
}
private void ShowQuestion()
{
RemoveAnswerButtons();
int questionIndex = Random.Range(0, questionPool.Length - 1);
QuestionData questionData = questionPool[questionIndex];
questionDisplayText.text = questionData.questionText;
for (int i = 0; i < questionData.answers.Length; i++)
{
GameObject answerButtonGameObject = answerButtonObjectPool.GetObject();
answerButtonGameObjects.Add(answerButtonGameObject);
answerButtonGameObject.transform.SetParent(answerButtonParent);
AnswerButton answerButton = answerButtonGameObject.GetComponent<AnswerButton>();
answerButton.Setup(questionData.answers[i]);
timeRemaining = currentRoundData.timeLimitInSeconds;
}
}
private void RemoveAnswerButtons()
{
while (answerButtonGameObjects.Count > 0)
{
answerButtonObjectPool.ReturnObject(answerButtonGameObjects[0]);
answerButtonGameObjects.RemoveAt(0);
}
}
private void UpdateTimeRemainingDisplay()
{
timeRemainingDisplayText.text = "TIJD: " + Mathf.Round(timeRemaining).ToString();
}
public void AnswerButtonClicked(bool isCorrect, bool isNotCorrect, float value)
{
if (isNotCorrect)
{
playerHealth -= damage;
FOUT.PlayOneShot(Fout);
Health -= value = 10;
HealthBar.size -= Health / 40f;
if (Health == 10)
{
KlikKlak.PlayOneShot(klikklak);
}
}
if (isCorrect)
{
GOED.PlayOneShot(Goed);
playerScore += currentRoundData.pointsAddedForCorrectAnswer;
scoreDisplayText.text = "SCORE: " + playerScore.ToString();
TotalscoreDisplayText.text = "Totaal " + playerScore.ToString();
}
if (questionPool.Length > questionIndex + 1)
{
questionIndex++;
ShowQuestion();
}
else
{
EndRound();
}
}
public void EndRound()
{
if (PlayerPrefs.GetFloat("HighScore") < playerScore)
PlayerPrefs.SetFloat("HighScore", playerScore);
isRoundActive = false;
questionDisplay.SetActive(false);
roundEndDisplay.SetActive(true);
}
public void ReturnToMenu()
{
SceneManager.LoadScene("MenuScreen");
}
// Update is called once per frame
void Update()
{
if (isRoundActive)
{
timeRemaining -= Time.deltaTime;
UpdateTimeRemainingDisplay();
if (timeRemaining <= 0f)
{
EndRound();
}
else
if (playerHealth <= 0)
{
playerHealth = 0;
EndRound();
}
}
}
}
What you could do is convert questionPool into a List, then after a random question has been picked, RemoveAt the index that random question was, so like:
int questionIndex = Random.Range(0, questionPool.Count -1); questionPool.RemoveAt(questionIndex);
Then that question will never appear again - you would then need a way to "refresh" your question pool, which I assume you already do after each "round" to generate a new set of questions anyway
Additionally, Random.Range when providing integer parameters is exclusive of the max value. So if you want to be able to return the last element of the array, you will want to remove the -1 on that, if your array has X elements in, randomly indexing into it (without missing the last item) is Random.Range(0, X)
Sorry now my script is visible I cant get it to work @Dibbie @HenryStrattonFW Thanks for your time
One mo, just got back from work, will try to get an example script thrown together for you.
Answer by HenryStrattonFW · Jan 20, 2017 at 08:03 PM
Ok so this is very skeleton code with placeholder QuestionData since I don't have access to all your scripts. But it should be enough to show you how you can use a list to store your questions, removing each questions as you ask it so that it cannot be asked again (since it is no longer in the list, and the list is where we randomly pick questions from).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private List<QuestionData> m_Questions;
void Start()
{
// I have to use an empty list since I dont have your currentRoundData but you do, so just create the list by passing it the array.
m_Questions = new List<QuestionData>(/*currentRoundData.questions*/);
ShowQuestion(GetQuestion());
}
private void ShowQuestion(QuestionData lQuestion)
{
// Show your question etc.
}
public void AnswerQuestionButton(bool isCorrect, float value)
{
// Note since correct and incorrect cannot both be true, you only need one argument as the other is implied.
if (isCorrect)
{
// do your stuff here for a good answer.
}
else
{
// the player is not so smart this time.
}
if (m_Questions.Count > 0)
{
// Show next question
ShowQuestion(GetQuestion());
}
else
{
// No more questions, game over i guess?
}
}
private QuestionData GetQuestion()
{
// Grab a question from the list (i'm using a random one, you could do them in order, up to you).
QuestionData lQuestion = m_Questions[Random.Range(0, m_Questions.Count)];
// Remove the question from the list, so that it cannot be asked again.
m_Questions.Remove(lQuestion);
// Return the selected question.
return lQuestion;
}
public class QuestionData
{
public string question;
public string answer;
}
}
So here are all the scripts, it's from a tutorial that i have followed on YouTube https://unity3d.com/learn/tutorials/topics/scripting/answer-button?playlist=17117
I am trying your code but i get errors :(:( @HenryStrattonFW
Try to reply in comments ins$$anonymous$$d of posting an answer.
As for my code, you should not be just dropping my code in as-is, it was just an example code to show you how you could use a list to avoid repeat questions.
Yo @HenryStrattonFW could you help me please through Team viewer. And is there an way to donate for your effort?
@Faysal-010 You're quite welcome, and no donation is necessary, I'm happy to help folks when I can. Good luck with the project.