How to make questions random, and make it loadable outside unity editor

So I have followed the Unity quiz Game Tutorial and would want to further improve the game. I have wondered how do you make the question in random not in the same order. Also, I would like the questions to be loaded not made inside the Unity Editor.

This is the QuestionData script
[System.Serializable]
public class AdditionQuestionData
{
public string questionText;
public AdditionAnswerData answers;
}

And this is the Game Controller
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;

public class AdditionGameController : MonoBehaviour
{
public AdditionSimpleObjectPool answerButtonObjectPool;
public Text questionText;
public Text scoreDisplay;
public Text timeRemainingDisplay;
public Transform answerButtonParent;

public GameObject questionDisplay;
public GameObject roundEndDisplay;
public Text highScoreDisplay;

private AdditionDataController dataController;
private AdditionRoundData currentRoundData;
private AdditionQuestionData[] questionPool;

private bool isRoundActive = false;
private float timeRemaining;
private int playerScore;
private int questionIndex;
private List<GameObject> answerButtonGameObjects = new List<GameObject>();

void Start()
{
	dataController = FindObjectOfType<AdditionDataController>();								// Store a reference to the DataController so we can request the data we need for this round

	currentRoundData = dataController.GetCurrentRoundData();							// Ask the DataController for the data for the current round. At the moment, we only have one round - but we could extend this
	questionPool = currentRoundData.questions;											// Take a copy of the questions so we could shuffle the pool or drop questions from it without affecting the original RoundData object

	timeRemaining = currentRoundData.timeLimitInSeconds;								// Set the time limit for this round based on the RoundData object
	UpdateTimeRemainingDisplay();
	playerScore = 0;
	questionIndex = 0;

	ShowQuestion();
	isRoundActive = true;
}

void Update()
{
	if (isRoundActive)
	{
		timeRemaining -= Time.deltaTime;												// If the round is active, subtract the time since Update() was last called from timeRemaining
		UpdateTimeRemainingDisplay();

		if (timeRemaining <= 0f)														// If timeRemaining is 0 or less, the round ends
		{
			EndRound();
		}
	}
}

void ShowQuestion()
{
	RemoveAnswerButtons();

	AdditionQuestionData questionData = questionPool[questionIndex];							// Get the QuestionData for the current question
	questionText.text = questionData.questionText;										// Update questionText with the correct text

	for (int i = 0; i < questionData.answers.Length; i ++)								// For every AnswerData in the current QuestionData...
	{
		GameObject answerButtonGameObject = answerButtonObjectPool.GetObject();			// Spawn an AnswerButton from the object pool
		answerButtonGameObjects.Add(answerButtonGameObject);
		answerButtonGameObject.transform.SetParent(answerButtonParent);
		answerButtonGameObject.transform.localScale = Vector3.one;

		AdditionAnswerButton answerButton = answerButtonGameObject.GetComponent<AdditionAnswerButton>();
		answerButton.SetUp(questionData.answers*);									// Pass the AnswerData to the AnswerButton so the AnswerButton knows what text to display and whether it is the correct answer*
  •   }*
    
  • }*
  • void RemoveAnswerButtons()*
  • {*
  •   while (answerButtonGameObjects.Count > 0)											// Return all spawned AnswerButtons to the object pool*
    
  •   {*
    
  •   	answerButtonObjectPool.ReturnObject(answerButtonGameObjects[0]);*
    
  •   	answerButtonGameObjects.RemoveAt(0);*
    
  •   }*
    
  • }*
  • public void AnswerButtonClicked(bool isCorrect)*
  • {*
  •   if (isCorrect)*
    
  •   {*
    
  •   	playerScore += currentRoundData.pointsAddedForCorrectAnswer;					// If the AnswerButton that was clicked was the correct answer, add points*
    
  •   	scoreDisplay.text = playerScore.ToString();*
    
  •   }*
    
  •   if(questionPool.Length > questionIndex + 1)											// If there are more questions, show the next question*
    
  •   {*
    
  •   	questionIndex++;*
    
  •   	ShowQuestion();*
    
  •   }*
    
  •   else																				// If there are no more questions, the round ends*
    
  •   {*
    
  •   	EndRound();*
    
  •   }*
    
  • }*
  • private void UpdateTimeRemainingDisplay()*
  • {*
  •   timeRemainingDisplay.text = Mathf.Round(timeRemaining).ToString();*
    
  • }*
  • public void EndRound()*
  • {*
  •   isRoundActive = false;*
    
  •   questionDisplay.SetActive(false);*
    
  •   roundEndDisplay.SetActive(true);*
    
  • }*
  • public void ReturnToMenu()*
  • {*
  •   SceneManager.LoadScene("MenuScreen");*
    
  • }*
    }
    Help please :slight_smile: Thanks!!

i made slight changes in your @DarkZknighT code added unselectedIndices list

public GameObject questionDisplay;
public GameObject roundEndDisplay;
public Text highScoreDisplay;
private AdditionDataController dataController;
private AdditionRoundData currentRoundData;
private AdditionQuestionData[] questionPool;
private bool isRoundActive = false;
private float timeRemaining;
private int playerScore;
private int questionIndex;
private List<GameObject> answerButtonGameObjects = new List<GameObject>();
private List<int> unselectedIndices= new  List<int> ();
    
void Start()
{
    dataController = FindObjectOfType<AdditionDataController>();                                // Store a reference to the DataController so we can request the data we need for this round
    currentRoundData = dataController.GetCurrentRoundData();                            // Ask the DataController for the data for the current round. At the moment, we only have one round - but we could extend this
    questionPool = currentRoundData.questions; 

    for (int i = 0; i < questionPool.Length; i ++)                                // For every AnswerData in the current QuestionData...
    {
        unselectedIndices.Add(i);
    }
    timeRemaining = currentRoundData.timeLimitInSeconds;                                // Set the time limit for this round based on the RoundData object
    UpdateTimeRemainingDisplay();
    playerScore = 0;
    questionIndex = UnityEngine.Random.Range(0,unselectedIndices.Count);
    ShowQuestion();
    isRoundActive = true;
}
void Update()
{
    if (isRoundActive)
    {
        timeRemaining -= Time.deltaTime;                                                // If the round is active, subtract the time since Update() was last called from timeRemaining
        UpdateTimeRemainingDisplay();
        if (timeRemaining <= 0f)                                                        // If timeRemaining is 0 or less, the round ends
        {
            EndRound();
        }
    }
}
void ShowQuestion()
{
    RemoveAnswerButtons();
    AdditionQuestionData questionData = questionPool[unselectedIndices[questionIndex]];                            // Get the QuestionData for the current question
    questionText.text = questionData.questionText;                                        // Update questionText with the correct text
    for (int i = 0; i < questionData.answers.Length; i ++)                                // For every AnswerData in the current QuestionData...
    {
        GameObject answerButtonGameObject = answerButtonObjectPool.GetObject();            // Spawn an AnswerButton from the object pool
        answerButtonGameObjects.Add(answerButtonGameObject);
        answerButtonGameObject.transform.SetParent(answerButtonParent);
        answerButtonGameObject.transform.localScale = Vector3.one;
        AdditionAnswerButton answerButton = answerButtonGameObject.GetComponent<AdditionAnswerButton>();
        answerButton.SetUp(questionData.answers*);                                    // Pass the AnswerData to the AnswerButton so the AnswerButton knows what text to display and whether it is the correct answer*

}
}
void RemoveAnswerButtons()
{
while (answerButtonGameObjects.Count > 0) // Return all spawned AnswerButtons to the object pool
{
answerButtonObjectPool.ReturnObject(answerButtonGameObjects[0]);
answerButtonGameObjects.RemoveAt(0);
}
}
public void AnswerButtonClicked(bool isCorrect)
{
if (isCorrect)
{
playerScore += currentRoundData.pointsAddedForCorrectAnswer; // If the AnswerButton that was clicked was the correct answer, add points
scoreDisplay.text = playerScore.ToString();
}

unselectedIndices.RemoveAt(questionIndex);
if(unselectedIndices.Count>0) // If there are more questions, show the next question
{
questionIndex= UnityEngine.Random.Range(0,unselectedIndices.Count);
ShowQuestion();
}
else // If there are no more questions, the round ends
{
EndRound();
}
}
private void UpdateTimeRemainingDisplay()
{
timeRemainingDisplay.text = Mathf.Round(timeRemaining).ToString();
}
public void EndRound()
{
isRoundActive = false;
questionDisplay.SetActive(false);
roundEndDisplay.SetActive(true);
}
public void ReturnToMenu()
{
SceneManager.LoadScene(“MenuScreen”);
}