I’m working through the Quiz Master project and I’ve encountered an interesting problem which I can’t solve myself.
Everything was working perfectly until I go to the point where you have to implement the Timer functionality. At that point the tutorial calls for you to refactor the code so that a lot of stuff that was happening in the Start method gets broken out into multiple methods that all call each other.
I must have done some thing wrong because my Timer works fine but the previous functionality is now broken but in a an interesting way.
The game runs but with the following error messages logging to the console:
- UnassignedReferenceException: The variable answerButtons of Quiz has not been assigned.
You probably need to assign the answerButtons variable of the Quiz script in the inspector.
UnityEngine.GameObject.GetComponent[T] () (at <4746c126b0b54f3b834845974d1a9190>:0)
Quiz.SetButtonState (System.Boolean state) (at Assets/Scripts/Quiz.cs:83)
Quiz.GetNextQuestion () (at Assets/Scripts/Quiz.cs:63)
Quiz.Start () (at Assets/Scripts/Quiz.cs:26) - NullReferenceException: Object reference not set to an instance of an object
Quiz.Update () (at Assets/Scripts/Quiz.cs:31) - IndexOutOfRangeException: Index was outside the bounds of the array.
Quiz.SetButtonState (System.Boolean state) (at Assets/Scripts/Quiz.cs:83)
Quiz.GetNextQuestion () (at Assets/Scripts/Quiz.cs:63)
Quiz.Update () (at Assets/Scripts/Quiz.cs:34)
Error 1 only happens on Start. Errors 2 and 3 recur on Update.
The answer text does not pull through to the buttons but the buttons remain clickable and change from one sprite to the other on click as they are supposed to (I changed the code slightly to have the button clicked change colour) The state change function also seems to be broken as you can now click multiple times to change your answer.
The question/answer text above the buttons changes as it is supposed to.
I’ve been back through the video’s and can’t spot where I’ve gone wrong but I think it’s something to do with the answerButton array the game uses to find the correct scriptable object. Can anyone look over my code and tell me what I’ve done wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class Quiz : MonoBehaviour
{
[Header("Questions")]
[SerializeField] TextMeshProUGUI questionText;
[SerializeField] QuestionSO question;
[Header("Answers")]
[SerializeField] GameObject[] answerButtons;
int correctAnswerIndex;
[Header("Button Colors")]
[SerializeField] Sprite defaultAnswerSprite;
[SerializeField] Sprite correctAnswerSprite;
[Header("Timer")]
[SerializeField] Image timerImage;
Timer timer;
void Start()
{
timer = FindObjectOfType<Timer>();
GetNextQuestion();
}
void Update()
{
timerImage.fillAmount = timer.fillFraction;
if(timer.loadNextQuestion)
{
GetNextQuestion();
timer.loadNextQuestion = false;
}
}
public void OnAnswerSelected(int index)
{
Image buttonImage;
if (index == question.GetCorrectAnswerIndex())
{
questionText.text = "Correct!";
buttonImage = answerButtons[index].GetComponent<Image>();
buttonImage.sprite = correctAnswerSprite;
}
else
{
correctAnswerIndex = question.GetCorrectAnswerIndex();
string correctAnswer = question.GetAnswer(correctAnswerIndex);
questionText.text = "Sorry, the correct answer was;\n" + correctAnswer;
buttonImage = answerButtons[index].GetComponent<Image>();
buttonImage.sprite = correctAnswerSprite;
}
SetButtonState(false);
timer.CancelTimer();
}
void GetNextQuestion()
{
SetButtonState(true);
SetDefaultButtonSprites();
DisplayQuestion();
}
void DisplayQuestion()
{
questionText.text = question.GetQuestion();
for (int i = 0; i < answerButtons.Length; i++)
{
TextMeshProUGUI buttonText = answerButtons[i].GetComponentInChildren<TextMeshProUGUI>();
buttonText.text = question.GetAnswer(i);
}
}
void SetButtonState(bool state)
{
for(int i = 0; 1 < answerButtons.Length; i++)
{
Button button = answerButtons[i].GetComponent<Button>();
button.interactable = state;
}
}
void SetDefaultButtonSprites()
{
for (int i = 0; i < answerButtons.Length; i++)
{
Image buttonImage = answerButtons[i].GetComponent<Image>();
buttonImage.sprite = defaultAnswerSprite;
}
}
}