Adding images into scripted objects

I was thinking about using the Quiz Master game course as a template for a simple trivia game. I want to add pictures/images into my game questions so I was thinking that I can add it into my scripted objects but I don’t know the method to make the images appear into my quiz game itself. What should I do to make this work?
3


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

[CreateAssetMenu(menuName = "Quiz Question", fileName = "New Question")]
public class QuestionSO : ScriptableObject
{
 [TextArea(2,6)]
 [SerializeField] string Question = "Enter new question here";
 [SerializeField] Sprite QuestionImage;
 [SerializeField] string[] answers = new string [4];
 [SerializeField] int correctAnswerIndex;
 public string GetQuestion()
 {return Question;}

 public string GetAnswer(int index)
 {return answers [index];}

 public int GetCorrectAnswerIndex()
 {return correctAnswerIndex;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;

public class Quiz : MonoBehaviour
{
    [Header("Questions")]
    [SerializeField] TextMeshProUGUI questionText;
    [SerializeField] List<QuestionSO> questions = new List<QuestionSO>();
    QuestionSO currentQuestion;
    [Header("Question Image")]
    public Sprite QuestionImage;

    [Header("Answers")]
    [SerializeField] GameObject[] answerButtons;
    int correctAnswerIndex;
    bool hasAnsweredEarly = true;

    [Header("Button Colors")]
    [SerializeField] Sprite defaultAnswerSprite;
    [SerializeField] Sprite correctAnswerSprite;

    [Header("Timer")]
    [SerializeField] Image timerImage;
    Timer timer;

    [Header("Scoring")]
    [SerializeField] TextMeshProUGUI scoreText;
    ScoreKeeper scoreKeeper;

    [Header("ProgressBar")]
    [SerializeField]Slider progressBar;

    public bool isComplete;

    void Awake()
    {
      timer = FindObjectOfType<Timer>();
      scoreKeeper = FindObjectOfType<ScoreKeeper>();
      progressBar.maxValue = questions.Count;
      progressBar.value = 0;
      QuestionImage = FindObjectOfType<Sprite>();
    }

    void Update()
    {
      timerImage.fillAmount = timer.fillFraction;
      if (timer.loadNextQuestion)
      {
         if(progressBar.value == progressBar.maxValue)
        {
            isComplete = true;
            return;
        }

        hasAnsweredEarly = false;
        GetNextQuestion();
        timer.loadNextQuestion = false;
      }
      else if(!hasAnsweredEarly && !timer.isAnsweringQuestion)
      {
          DisplayAnswer(-1);
          SetButtonState(false);
      }
      
    }

    public void OnAnswerSelected(int index)
    {   
        hasAnsweredEarly = true;
        DisplayAnswer(index);
        SetButtonState (false);
        timer.CancelTimer();
        scoreText.text = "Score: "+scoreKeeper.CalculateScore()+"%";
    }
    
    void DisplayAnswer(int index)
    {
        Image buttonImage;
        if (index == currentQuestion.GetCorrectAnswerIndex())
        {
            questionText.text = "Correct!";
            buttonImage = answerButtons[index].GetComponent<Image>();
            buttonImage.sprite = correctAnswerSprite;
            scoreKeeper.IncrementCorrectAnswers();
        }
        else
        {
            correctAnswerIndex = currentQuestion.GetCorrectAnswerIndex();
            string correctAnswer = currentQuestion.GetAnswer(correctAnswerIndex);
            questionText.text = "Sorry, the correct answer was;\n " + correctAnswer;
            buttonImage = answerButtons[correctAnswerIndex].GetComponent<Image>();
            buttonImage.sprite = correctAnswerSprite; 
        }
    }
    
    void GetNextQuestion()
    {
        if (questions.Count > 0)
      {
        SetButtonState(true);
        SetDefaultButtonSprites();
        GetRandomQuestion();
        DisplayQuestion();
        progressBar.value++;
        scoreKeeper.IncrementQuestionsSeen();
      }
    }

    void GetRandomQuestion()
    {
        int index = Random.Range(0, questions.Count);
        currentQuestion = questions[index];
        if (questions.Contains(currentQuestion))
        {
           questions.Remove(currentQuestion);
        }
    }

    void DisplayQuestion() 
    {
      questionText.text = currentQuestion.GetQuestion();
      
      for (int i = 0; i < answerButtons.Length ; i++)
      {
        TextMeshProUGUI buttonText = answerButtons[i].GetComponentInChildren<TextMeshProUGUI>();
        buttonText.text = currentQuestion.GetAnswer(i);
      }
    }

    void SetButtonState (bool state)
    {
      for (int i = 0; i < 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;
        }
    } 
}

In your Quiz class, The image should be of type Image, not Sprite. Then you can set Image.sprite to the Sprite in the ScriptableObject in the same way you set the answer sprites

So I change the Sprite into Image in the quiz class then change the Sprite into Image.Sprite in the scripted object?

no, your scriptable object is fine except that you will need to expose the image.

// In QuestionSO
public Sprite GetQuestionImage()
{
    return QuestionImage;
}

Then you need to make changes where you want to display the image (the Quiz class). Here are changes you can make:

public class Quiz : MonoBehaviour
{
    [Header("Question Image")]
    [SerializeField] Image questionImage;  // Change this to Image and add SerializeField so you can assign it in the inspector

    void Awake()
    {
      timer = FindObjectOfType<Timer>();
      scoreKeeper = FindObjectOfType<ScoreKeeper>();
      progressBar.maxValue = questions.Count;
      progressBar.value = 0;
      //QuestionImage = FindObjectOfType<Sprite>(); // remove this, you will assign it in the inspector
    }

    void DisplayQuestion() 
    {
      questionText.text = currentQuestion.GetQuestion();
      questionImage.sprite = currentQuestion.GetQuestionImage(); // assign image from scriptable object
      
      for (int i = 0; i < answerButtons.Length ; i++)
      {
        TextMeshProUGUI buttonText = answerButtons[i].GetComponentInChildren<TextMeshProUGUI>();
        buttonText.text = currentQuestion.GetAnswer(i);
      }
    }
}

Once you have made these changes, you need to go into Unity and drag the Image from the hierarchy into the Question Image field of the Quiz component.

1 Like

Many thanks.

It’s my pleasure

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms