How to make questions & answers random in my script C#?

Hello Unity Answers,

I want to make my questions and answers random because at the moment the question is the same one when the player collides into the cube and the answers are in the same place as well.

Is there away to make it change randomly upon collision with a cube.

So for example, if the player runs out of time and is sent back to the start, I would like a new question to appear on screen, not “What year did Ebola begin?”

Also the answer is 1976, which is set in the top left button, can I place this somewhere else?

Any ideas/help/suggestions would be much appreciated.

alt text

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

public class Question1 : MonoBehaviour {
	
	private Rect windowRect = new Rect (500, 100, 400, 200); //Window size
	public bool question1;
	private int count;
	public Text countText;

	private bool showTimer = true;
	private float Timer = 10f;

	
	void start()
	{
		count = 0;
		SetCountText ();
	}


	void FixedUpdate(){
		if (showTimer == true) {
			Timer -= Time.deltaTime;
		}

		if (Timer <= 0f) {
			showTimer = false;
			Timer = 10f;
			Destroy (this.gameObject);
			Application.LoadLevel (Application.loadedLevel);

		}
	}

	
	void OnGUI(){
		{
			windowRect = GUI.Window (0, windowRect, WindowFunction, "Ebola Quiz Island"); //window on screen 
		}
	}


	void WindowFunction (int windowID) 
	{
		// Draw any Controls inside the window here

		GUI.Label (new Rect (30, 25, 200, 50), " What year did Ebola begin?"); // Question
		
		if (GUI.Button (new Rect (20, 100, 100, 30), "1976")) // Correct Answer
		{
			Destroy (this.gameObject);
			count = count + 1;
			SetCountText ();
		} 

		if (GUI.Button (new Rect (280, 100, 100, 30), "1986")) //Wrong answer  
		{
			Destroy (this.gameObject);
			Application.LoadLevel(Application.loadedLevel);
		}

		if (GUI.Button (new Rect (20, 150, 100, 30), "1996")) // wrong answer
		{
			Destroy (this.gameObject);
			Application.LoadLevel(Application.loadedLevel);
		}

		if (GUI.Button (new Rect (280, 150, 100, 30), "1966")) // wrong answer
		{
			Destroy (this.gameObject);
			Application.LoadLevel(Application.loadedLevel);
		}

		if (showTimer == true) 
		{
			GUI.Label (new Rect (300, 25, 200, 50), "Timer: " + Timer.ToString ("F0"));
		}


	}

	void SetCountText()
		{
			countText.text = "Score: " + count.ToString ();
		}


}

The easiest way to implement this is to create instances of a question class (preferrably not in a scene but in the project folder) which hold the question and the possible answers and let them handle randomizing the button positions.

using UnityEngine;
using System.Collections.Generic;

// A Question
public class MyQuestion : ScriptableObject {

    // the question
    public string question;

    // the different answers (answer[0] is right answer by default)
    public string[] answers;

    // the order, in which answers are displayed
    private int[] m_order;

    //This does not work outside the Editor
#if UNITY_EDITOR
    // Create Questions from Folder Context Menu
    [UnityEditor.MenuItem("Assets/Create/Question")]
    public static void CreateQuestion()
    {
        string resourcePath = "Assets/Resources/Questions";

        // makes sure you have a directory to save your question to.
        if (!System.IO.Directory.Exists(Application.dataPath + "/Resources"))
        {
            UnityEditor.AssetDatabase.CreateFolder("Assets", "Resources");
        }
        if (!System.IO.Directory.Exists(Application.dataPath + "/Resources/Questions"))
        {
            UnityEditor.AssetDatabase.CreateFolder("Assets/Resources", "Questions");
        }

        // create question
        MyQuestion myQuestion = CreateInstance<MyQuestion>();
        
        // name question
        int questions = UnityEditor.AssetDatabase.FindAssets("", new string[1]{resourcePath}).Length;
        myQuestion.name = "Question_" + questions;

        // save question to project folder
        UnityEditor.AssetDatabase.CreateAsset(myQuestion, resourcePath + "/" + myQuestion.name + ".asset");
    }
#endif

    public void OnEnable()
    {
        if (question == null)
        {
            question = "";
        }
        if (answers == null)
        {
            answers = new string[4] { "", "", "", "" };
        }
        // Prevents exceptions in OnGUI if you forget to call RandomizeAnswers() 
        m_order = new int[answers.Length];
        for (int i = 0; i < m_order.Length; ++i)
        {
            m_order *= i;*

}
}

// Randomizes the order in which answers are presented
public void RandomizeAnswers()
{
System.Random random = new System.Random();
List order = new List();

// get indices
for (int i = 0; i < answers.Length; ++i)
{
order.Add(i);
}

m_order = new int[answers.Length];
int index = 0;

// shuffle indices
while (order.Count > 0)
{
int index2 = random.Next(order.Count);
m_order[index] = order[index2];
order.RemoveAt(index2);
++index;
}
}

/* Your Question display function
* returns true (right answer), false (wrong answer) or null (nothing chosen) */
public bool? ShowQuestion(Rect _area)
{
// bool that can be true, false or null. ? makes any struct nullable
bool? result = null;

// just a simple layout
GUILayout.BeginArea(_area);

// display question
GUILayout.Label(question);

for (int i = 0; i < answers.Length; ++i)
{
// display buttons in random order
if (GUILayout.Button(answers[m_order*]))
_
{_
if (m_order == 0) // right choice
_{
result = true;
}
else // wrong choice
{
result = false;
}
}
}*
GUILayout.EndArea();_

return result;
}

}
(You can save instances of classes that inherit from ScriptableObject as assets in in your project)
Now to randomize the questions themselves, one way to go is use a central question pool that holds all questions and ask for new question every time the question trigger is entered.
using UnityEngine;
using System.Collections;

// Singleton for managing the question pool
public class MyQuestionPool {

// static instance
private static MyQuestionPool m_questionPool = null;

// all questions
private MyQuestion[] m_questions = null;

private System.Random m_random = null;

private MyQuestionPool()
{
m_random = new System.Random();
InitQuestions();
}

// Loads questions
private void InitQuestions()
{
/* Resources.Load looks inside the Assets/Resources-folder
* full path is Assets/Resources/Questions */
m_questions = Resources.LoadAll(“Questions”);
}

// Gets the question pool
public static MyQuestionPool Instance
{
get
{
if (m_questionPool == null)
{
m_questionPool = new MyQuestionPool();
}
return m_questionPool;
}
}

// Gets a random question
public MyQuestion GetQuestion()
{
if (m_questions != null && m_questions.Length > 0)
{
int index = m_random.Next(m_questions.Length);
m_questions[index].RandomizeAnswers();
return m_questions[index];
}

return null;
}
}

At last, the trigger:
using UnityEngine;
using System.Collections;

// A question trigger
public class MyQuestionTrigger : MonoBehaviour {

// current question
private MyQuestion m_question = null;

public void OnGUI()
{
// Display Question
if (m_question)
{
bool? result = m_question.ShowQuestion(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 200, 400, 400));

if (result == null)
{
// no answer, wait…
return;
}
else if (result == true)
{
// right answer given
}
else
{
// wrong answer given
}

// discard question
m_question = null;
}
}

public void OnTriggerEnter(Collider _col)
{
// Get Question
m_question = MyQuestionPool.Instance.GetQuestion();
}
}
With this you can add questions until you run out of RAM, Array-Indices or ideas for new questions. You can edit them in your inspector. Just do not delete questions or it will screw with the way new questions are named.