Ozymandius
Ozymandius

Reputation: 68

Setting levels in a quiz game

This is my first post to Stack Overflow so please be gentle. I have followed the video tutorial at https://learn.unity.com/tutorial/live-session-quiz-game-1 and have been able to successfully modify it so that images are shown as questions instead of text. The next step for me is to divide my game into Levels. I have added the appropriate extra 'Rounds' in the DataController object referred to at the end of video 3 start of video 4 so that it now looks like this:

DataController Screenshot

So here is the question, if I want to add a set of buttons to a Levels page, and then add an OnClick event to each, how do I point that OnClick event specifically to the set of questions for each Level? I think I need to point the onClick at a script passing a variable that is the level number, but not sure how to do it and so far searches of StackOverflow and YouTube haven't really helped?

EDIT

I have done the following and I seem to be a lot closer:

  1. Created a new scene called LevelSelect and added the buttons I need for the levels to it;
  2. I created a script in the scene called LevelSelectController and to this I added the button registration script provided by Lothan;
  3. I registered the buttons as suggested via drag and drop;
  4. I created a Function within the LevelSelectController script called StartGame, this had one line: Debug.Log("Button pressed is: Level " + (setLevel + 1)); I ran the script and the buttons responded as expected;

All I am struggling with now his how to get the button press to pass the integer for the level number to the allRoundData variable in the DataController. The code for each script looks like this:

DataController

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

public class DataController : MonoBehaviour
{
public RoundData[] allRoundData;
public int currentLevel;

// Start is called before the first frame update
void Start()
{
    DontDestroyOnLoad (gameObject);

    SceneManager.LoadScene ("MenuScreen");
}

public RoundData GetCurrentRoundData()
{
    return allRoundData [currentLevel];
}

// Update is called once per frame
void Update()
{

}
}

LevelSelectController

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

public class LevelSelectController : MonoBehaviour
{
    public List<Button> buttonsList = new List<Button>();
    private DataController dataController;

    public void StartGame(int setLevel)
    {
        Debug.Log("Button pressed is: Level " + (setLevel + 1));
    }
}

GameController

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

public class GameController : MonoBehaviour
{
    public Text questionText;
    public Image questionImage;
    public SimpleObjectPool answerButtonObjectPool;
    public Transform answerButtonParent;
    private DataController dataController;
    private RoundData currentRoundData;
    private QuestionData[] questionPool;

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

    // Start is called before the first frame update
    void Start()
    {
        dataController = FindObjectOfType<DataController> ();
        currentRoundData = dataController.GetCurrentRoundData ();
        questionPool = currentRoundData.questions;
        timeRemaining = currentRoundData.timeLimitInSeconds;

        playerScore = 0;
        questionIndex = 0;

        ShowQuestion ();
        isRoundactive = true;
    }

    private void ShowQuestion()
    {
        RemoveAnswerButtons ();
        QuestionData questionData = questionPool[questionIndex];
        questionText.text = questionData.questionText;

        questionImage.transform.gameObject.SetActive(true);
        questionImage.sprite = questionData.questionImage;

        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]);
        }

    }

    private void RemoveAnswerButtons()
    {
        while (answerButtonGameObjects.Count > 0)
        {
            answerButtonObjectPool.ReturnObject(answerButtonGameObjects[0]);
            answerButtonGameObjects.RemoveAt(0);
        }
    }

    // Update is called once per frame
    void Update()
    {

    }
}

How do I now pass the value of setLevel in LevelSelectController to currentLevel in the DataController script?

Upvotes: 2

Views: 500

Answers (2)

Ozymandius
Ozymandius

Reputation: 68

With a little extra research I was able to use a static variable along with Lothan's suggestion to get to the solution. Here is the modified code:

LevelSelectController

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

public class LevelSelectController : MonoBehaviour
{
    static public int currentLevel
    public List<Button> buttonsList = new List<Button>();

    void Start()
    {
        for(int i = 0; i < buttonsList.Count; i++)
    {
        int levelNum = i;
        buttonsList[i].onClick.AddListener(() => {currentLevel = levelNum;}); 
    }     
}

    public void StartLevel()
    {
        SceneManager.LoadScene ("Game");
    }
}

And only one edit needed in the Start() of GameController.cs, from

currentRoundData = dataController.GetCurrentRoundData ();

to:

currentRoundData = dataController.GetCurrentRoundData (LevelSelectController.currentLevel);

Upvotes: 0

Lotan
Lotan

Reputation: 4283

Welcome to StackOverflow!

You can do it using different ways, but one could be:

First register all the buttons:

List<Button> buttonsList = new List<Button>();

Then assign to each button the behaviour to do when onClick (registering the listener) passing the info of the corresponding DataController:

for(int i = 0; i < buttonsList.Count; i++)
{
    buttonsList[i].onClick.AddListener(() => SetLevel(DataController.allRoundData[i])) 
}      

There are some leaps of faith in this current answer cause I don't know about your code, but if you have doubts, comment and I'll update the answer ^^

Upvotes: 1

Related Questions