Setting levels in a quiz game - c#

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:
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:
Created a new scene called LevelSelect and added the buttons I need for the levels to it;
I created a script in the scene called LevelSelectController and to this I added the button registration script provided by Lothan;
I registered the buttons as suggested via drag and drop;
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?

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 ^^

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

Related

How to make object appear when a certain torso is called using C# in Unity

This is the code I used for a tutorial
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Trial_Changer : MonoBehaviour
{
[Header("Sprite To Change")]
public SpriteRenderer bodyPart;
[Header("Sprites to Cycle Through")]
public List<Sprite> options = new List<Sprite>();
public static int currentTorsoOption = 0;
public void NextOption ()
{
currentTorsoOption++;
if (currentTorsoOption >= options.Count)
{ currentTorsoOption = 0; }
bodyPart.sprite = options[currentTorsoOption];
}
public void PreviousOption()
{
currentTorsoOption--;
if (currentTorsoOption <= 0)
{ currentTorsoOption = options.Count - 1; }
bodyPart.sprite = options[currentTorsoOption];
}
}
**This is the code I am using to try to say "if torso 2 is called, create object"
**
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpeechAppears : MonoBehaviour
{
public GameObject speechBubbleTOSpawn;
private int Torso = Trial_Changer.currentTorsoOption;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Torso == 2)
{
Instantiate(speechBubbleTOSpawn);
}
}
}
Except the torso just appears always.
What do I do to fix this?
I want an object to appear when torso 2 is on the screen but instead the object is just always present. What do I do ?
The culprit is this line :
private int Torso = Trial_Changer.currentTorsoOption;
Since you assign value Torso only once at the start of the game, its value always be the same.
Try this :
private int Torso => Trial_Changer.currentTorsoOption;
This change Torso from a field to a property, and when Torso is used, it will read the current value of Trial_Changer.currentTorsoOption.

Unity Rewarded Ads coding Rewards

How can i make it so after watching 2 rewarded ads all the levels in my game are unlocked and playable.
Currently i have it so you have to complete the level in order to unlock that level and be able to play it at any given time.
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed");
// Grant a reward.
// Load another ad:
Advertisement.Load(_adUnitId, this);
}
}
You can use the PlayerPrefs system to track the number of ads they've watched. Increment that PlayerPref each time they watch an ad.
Then change your level configuration code to check for that PlayerPref in addition to which levels they've completed.
Unity uses PlayerPrefs to achieve level unlocking.
Level Structure:
Add a script where the level is confirmed to pass.
public int jiesuo;
jiesuo = SceneManager.GetActiveScene().buildIndex;
PlayerPrefs.SetInt("jiesuo", jiesuo);
Then add the level script to the level artboard.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class level : MonoBehaviour
{
Button[] button;
public GameObject panl;
int jiesuo1;
void Start()
{
jiesuo1 = PlayerPrefs.GetInt("jiesuo");
button = new Button[panl.transform.childCount];
for (int i = 0; i < panl.transform.childCount; i++)
{
button[i] = panl.transform.GetChild(i).GetComponent<Button>();
}
for (int i = 0; i < button.Length; i++)
{
button[i].interactable = false;
}
for (int i = 0; i < jiesuo1+1; i++)
{
button[i].interactable = true;
}
}
void Update()
{
}
}
button add:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class levelbutton : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public void OnStartGame(int SceneNumber)
{
SceneManager.LoadScene(SceneNumber);
}
void Update()
{
}
}

C# errror "CS0116: A namespace cannot directly contain members such as fields or methods"

I get an error, Assets\scripts\Skins.cs(9,12): error CS0116: A namespace cannot directly contain members such as fields or methods on the Internet they write what it means incorrectly placed brackets, but I don’t see any errors
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public GameObject choise1;
public GameObject choise2;
public GameObject choise3;
public int skin = 1;
public class Skins : MonoBehaviour {
void Choise () {
if (Input.GetMouseDown(choise1)){
choise2.SetActive (false);
}
}
}
GameObject and that int skin need to be under Skins class, like Choise
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Skins : MonoBehaviour {
public GameObject choise1;
public GameObject choise2;
public GameObject choise3;
public int skin = 1;
void Choise () {
if (Input.GetMouseDown(choise1)){
choise2.SetActive (false);
}
}
}
If you still have some problems here, because I don't know what are u trying to do with that choiseX, maybe you need to create them.
I mean, maybe u are trying to write something like this
void Choise () {
var GameObject choise1 = new GameObject();
var GameObject choise2 = new GameObject();
var GameObject choise3 = new GameObject();
int skin = 1;
if (Input.GetMouseDown(choise1)){
choise2.SetActive (false);
}
}

Why is the GUI components obsolete?

I'm currently making a remake of Dreadhalls in Unity3D. I got the code but I got 2 errors:
Assets\Standard Assets\Utility\ForcedReset.cs(6,27): error CS0619: 'GUITexture' is obsolete: 'GUITexture has been removed. Use UI.Image instead.'
Assets\Standard Assets\Utility\SimpleActivatorMenu.cs(10,16): error CS0619: 'GUIText' is obsolete: 'GUIText has been removed. Use UI.Text instead.'
I tried replacing them with the items given to me in the error, but it is still getting errors saying that the namespacee name UI is not found. I'm still not used to Unity so I need some help.
Here is the code of ForcedReset.cs:
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityStandardAssets.CrossPlatformInput;
[RequireComponent(typeof (GUITexture))]
public class ForcedReset : MonoBehaviour
{
private void Update()
{
// if we have forced a reset ...
if (CrossPlatformInputManager.GetButtonDown("ResetObject"))
{
//... reload the scene
SceneManager.LoadScene(SceneManager.GetSceneAt(0).name);
}
}
}
And here is the code of SimpleActivatorMenu.cs:
using System;
using UnityEngine;
namespace UnityStandardAssets.Utility
{
public class SimpleActivatorMenu : MonoBehaviour
{
// An incredibly simple menu which, when given references
// to gameobjects in the scene
public GUIText camSwitchButton;
public GameObject[] objects;
private int m_CurrentActiveObject;
private void OnEnable()
{
// active object starts from first in array
m_CurrentActiveObject = 0;
camSwitchButton.text = objects[m_CurrentActiveObject].name;
}
public void NextCamera()
{
int nextactiveobject = m_CurrentActiveObject + 1 >= objects.Length ? 0 : m_CurrentActiveObject + 1;
for (int i = 0; i < objects.Length; i++)
{
objects[i].SetActive(i == nextactiveobject);
}
m_CurrentActiveObject = nextactiveobject;
camSwitchButton.text = objects[m_CurrentActiveObject].name;
}
}
}
Is there a problem?
GUIText and Other Elements have been Removed from the Newer Versions of Unity Due to Combability and Some Other Issues!
Fix for GUI Text
Make Sure that you Import the Following Line of Statement in your Code:-
using UnityEngine.UI;
Then, Simply Change from
public GUIText camSwitchButton;
to
public Text camSwitchButton;
Fixed for GUI Texture
This Fix Gave Me Some Warning on Other Files But Worked Properly! It Might Be Fixed in the Upcoming Updates of Unity!
Make Sure that you Import the Following Line of Statement in your Code:-
using UnityEngine.UI;
Then, Change from this Line of Code
[RequireComponent(typeof (GUITexture))]
to,
[RequireComponent(typeof(Texture))]
Hope So this Helps! I Have Checked it and it works Fine But Just Gave Me Some Warnings which I Don't Care!
But It will be Fine and will be Fixed in Some Upcoming Versions of Unity!
Fixed
For the ForcedReset.cs file change its contents with the following code:
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityStandardAssets.CrossPlatformInput;
[RequireComponent(typeof(Texture))]
public class ForcedReset : MonoBehaviour
{
private void Update()
{
// if we have forced a reset ...
if (CrossPlatformInputManager.GetButtonDown("ResetObject"))
{
//... reload the scene
SceneManager.LoadScene(SceneManager.GetSceneAt(0).name);
}
}
}
For the SimpleActivatorMenu.cs file change its contents with the following:
using System;
using UnityEngine;
using UnityEngine.UI;
namespace UnityStandardAssets.Utility
{
public class SimpleActivatorMenu : MonoBehaviour
{
// An incredibly simple menu which, when given references
// to gameobjects in the scene
public Text camSwitchButton;
public GameObject[] objects;
private int m_CurrentActiveObject;
private void OnEnable()
{
// active object starts from first in array
m_CurrentActiveObject = 0;
camSwitchButton.text = objects[m_CurrentActiveObject].name;
}
public void NextCamera()
{
int nextactiveobject = m_CurrentActiveObject + 1 >= objects.Length ? 0 : m_CurrentActiveObject + 1;
for (int i = 0; i < objects.Length; i++)
{
objects[i].SetActive(i == nextactiveobject);
}
m_CurrentActiveObject = nextactiveobject;
camSwitchButton.text = objects[m_CurrentActiveObject].name;
}
}
}

Unity Quiz Game Score in C#

I am making a quiz game in the unity from the unity live session quiz game tutorials everything is working fine except somehow the score isn't working when i Click the button it should add 10 score to the Score. Here are the tutorials : https://unity3d.com/learn/tutorials/topics/scripting/intro-and-setup?playlist=17117 and the code for my Game Controller :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
public class GameController : MonoBehaviour {
public Text questionDisplayText;
public Text scoreDisplayText;
public Text timeRemainingDisplayText;
public SimpleObjectPool answerButtonObjectPool;
public Transform answerButtonParent;
public GameObject questionDisplay;
public GameObject roundEndDisplay;
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>();
// Use this for initialization
void Start ()
{
dataController = FindObjectOfType<DataController> ();
currentRoundData = dataController.GetCurrentRoundData ();
questionPool = currentRoundData.questions;
timeRemaining = currentRoundData.timeLimitInSeconds;
UpdateTimeRemainingDisplay();
playerScore = 0;
questionIndex = 0;
ShowQuestion ();
isRoundActive = true;
}
private void ShowQuestion()
{
RemoveAnswerButtons ();
QuestionData questionData = questionPool [questionIndex];
questionDisplayText.text = questionData.questionText;
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);
}
}
public void AnswerButtonClicked(bool isCorrect)
{
if (isCorrect)
{
playerScore += currentRoundData.pointsAddedForCorrectAnswer;
scoreDisplayText.text = "Score: " + playerScore.ToString();
}
if (questionPool.Length > questionIndex + 1) {
questionIndex++;
ShowQuestion ();
} else
{
EndRound();
}
}
public void EndRound()
{
isRoundActive = false;
questionDisplay.SetActive (false);
roundEndDisplay.SetActive (true);
}
public void ReturnToMenu()
{
SceneManager.LoadScene ("MenuScreen");
}
private void UpdateTimeRemainingDisplay()
{
timeRemainingDisplayText.text = "Time: " + Mathf.Round (timeRemaining).ToString ();
}
// Update is called once per frame
void Update ()
{
if (isRoundActive)
{
timeRemaining -= Time.deltaTime;
UpdateTimeRemainingDisplay();
if (timeRemaining <= 0f)
{
EndRound();
}
}
}
}
and my answer Button Code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class AnswerButton : MonoBehaviour {
public Text answerText;
private AnswerData answerData;
private GameController GameController;
// Use this for initialization
void Start ()
{
GameController = FindObjectOfType<GameController> ();
}
public void Setup(AnswerData data)
{
answerData = data;
answerText.text = answerData.answerText;
}
public void HandleClick()
{
GameController.AnswerButtonClicked (answerData.isCorrect);
}
}
and Answer Data :
using UnityEngine;
using System.Collections;
[System.Serializable]
public class AnswerData
{
public string answerText;
public bool isCorrect;
}
If everything is working fine (the whole code gets executed correctly, which I presume at this point), you probably did not set the data correctly. In your Game Controller, you have the line
playerScore += currentRoundData.pointsAddedForCorrectAnswer;
in your AnswerButtonClicked method which should add an amount you defined to the score if the answer is correct. Since I presume that your whole code is running fine (I can't see your in-engine setup, only the code here, which looks like the one in the tutorial), this is probably the first location where to look at the error. This value is probably set in the Unity Inspector or via another script, so you may want to go check in other files or the Editor.
The next thing to check is, if the buttons are correctly linked via their event handler. This can be checked by looking at the inspector. In the tutorial series this step is done in part Click to answer at the end of the video.

Categories