0
\$\begingroup\$

I'm making a trivia game on Unity, everything works fine and now I'm trying to save and retrieve the stats of a game. I have listed most of the stats (score, highscore, points) but now I would like to add the best series of consecutive correct answers, and I don't know how I can exactly set this value.

In theory I know that during the game when a correct answer is given, a counter is triggered to record the number of consecutive correct answers and it stops at the wrong answer. Then at the next triggered series the method checks if the new count is the best. But, as I'm a beginner, I don't know how I can save this kind of streak.

Could you help me please?

In order to understand the context:

public class ansButtonScript : MonoBehaviour {

public Text txt;
public Sprite im_basic, im_corr, im_wrong;

#region Pts&Score
    public int points = 1;
    string _allPts = "totalPts";
    static int totalPts;
    static int score = 0;
    string _score = "score";
    static int hiscore = 0;
    string _hiScore = "hiScore";
#endregion

public AudioClip sound_win, sound_loose;
public GameObject correctTxt, wrongTxt;

#region Cache Refs
public GameObject _canvas, _barInt;
private qManager _qManagerCanvas;
private progBarScript _progBarInt;
private countdownScript _barCountdown;
#endregion

public void Start()
{
    totalPts = PlayerPrefs.GetInt(_allPts);

    _qManagerCanvas = _canvas.GetComponent<qManager>();
    _progBarInt = _barInt.GetComponent<progBarScript>();
    _barCountdown = _barInt.GetComponent<countdownScript>();
}

public void updateTxt(string str_text)
{
    txt.text=str_text;
    GetComponent<Image>().sprite = im_basic;
}

public void SelectButton()
{
    if(_qManagerCanvas.canPlay)
    {
        _progBarInt.barTimeStop();
        _qManagerCanvas.canPlay = false;
        string reponse = _qManagerCanvas.reponse;

        if(transform.Find("Text").GetComponent<Text>().text == reponse)
        {
            //good answer
            GetComponent<AudioSource>().PlayOneShot(sound_win);     //SFX Win
            vraiTxt.SetActive(true);                                //animation Correct
            updateTrue();                                           //the answer is shown
            StartCoroutine(addPoints());                            
            StartCoroutine(next_question());                        //new question
        }
        else
        {
            //wrong answer
            GetComponent<AudioSource>().PlayOneShot(sound_loose);
            fauxTxt.SetActive(true);
            updateFalse();                                      //the answer isn't shown
            StartCoroutine(next_question());                    //new question
            _barCountdown.ResetTimer();
        }
    }
}

IEnumerator addPoints()
{
    yield return new WaitForSeconds(2.2f);
    playerStats.UpMoney += points;              
    score++;                                    //set the nb of correct answers
    saveAllPts();                               //save the nb of points 
    PlayerPrefs.SetInt(_score, score);          //save the nb of corr answers
    SaveBestScore();                            //save best score
}

IEnumerator next_question()
{
    yield return new WaitForSeconds(3f);
    _qManagerCanvas.tirage();
    _barCountdown.ResetTimer();
    correctTxt.SetActive(false);
    wrongTxt.SetActive(false);
}

public void updateTrue()
{
    GetComponent<Image>().sprite = im_corr;
}
public void updateFalse()
{
    GetComponent<Image>().sprite = im_wrong;
}

public void SaveBestScore()
{
    if (score > PlayerPrefs.GetInt(_hiScore))
    {
        PlayerPrefs.SetInt(_hiScore, score);
    }
}

public void saveAllPts()
{
    totalPts += points;
    PlayerPrefs.SetInt(_allPts, totalPts);
}
}
\$\endgroup\$
0
\$\begingroup\$

It's hard to answer without seeing your code, but it would be something like this:

int consecutiveHits = 0;
int consecutiveHitsRecord = 0;

public void OnAnswerQuestion(int answer)
{
    if(answer == correctAnswer)
    {
        consecutiveHits++; //Increments the count of hits
    }
    else
    {
        // Check if the series is a record
        if(consecutiveHits > consecutiveHitsRecord)
        {
            consecutiveHitsRecord  = consecutiveHits;
        }

        consecutiveHits = 0; // Restarts the counter
    }
}

public void OnEndGame()
{
    if(consecutiveHits > consecutiveHitsRecord)
    {
        consecutiveHitsRecord  = consecutiveHits;
    }
}

Of course this is a pseudocode, you have to adapt it with your own! The first part goes where you're checking if the answer is correct and the second where the game ends.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. Precisely I didn't know how to code that. I was stuck on how to proceed so that ConsecutiveAnswer = two CorrectAnswers in a row (with no WrongAnswer in between). I know that's silly, but maybe I'm imagining something more complicated than it is. \$\endgroup\$ – ScottMass Jul 14 '18 at 9:50
  • \$\begingroup\$ I'd recommend upping your record inside the if block, rather than the else. eg. consecutiveHitsRecord = Mathf.Max(consecutiveHitsRecord, consecutiveHits); immediately after incrementing consecutiveHits. Otherwise a streak ending with correctly answering the last question of the match doesn't get counted, because there's no wrong answer after it to force it into the else branch. \$\endgroup\$ – DMGregory Jul 14 '18 at 11:18
  • \$\begingroup\$ This is exactly what this code does. If the answer is wrong, the counting of hits in a row is reset. Or maybe I am not understanding correctly! @DMGregory You're right! I'll edit the answer. \$\endgroup\$ – Nathalia Soragge Jul 14 '18 at 20:36
  • \$\begingroup\$ Thank you very much to both of you Nathalia & @DMGregory. Your help was really useful. You solved my problem and I've achieved finally to get the stats that I wanted to display. Thanks again! :) \$\endgroup\$ – ScottMass Jul 15 '18 at 7:56
  • \$\begingroup\$ No problem, glad to help (: \$\endgroup\$ – Nathalia Soragge Jul 15 '18 at 8:05
1
\$\begingroup\$

If I am understanding correctly you want to keep a running score that resets on an incorrect answer I would use events. Put the EventManager and ScoreManager on an GameObject somewhere in your scene.

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

public class EventManager : MonoBehaviour
{
    //Create a new delegate
    public delegate void CorrectAnswer();
    //Create the event for the delegate
    public event CorrectAnswer OnCorrectAnswer;

    //here's the function we'll call from otherscripts to tell whatever is subscribed (ScoreManager) in this case
    //to do whatever it needs to do on a correct answer given
    public void TriggerOnCorrectAnswer()
    {
        if (OnCorrectAnswer != null)
        {
            OnCorrectAnswer();
        }
    }

    public delegate void WrongAnswer();
    public event WrongAnswer OnWrongAnswer;

    public void TriggerOnWrongAnswer()
    {
        if (OnWrongAnswer != null)
        {
            OnWrongAnswer();
        }
    }
}

I'm only using "Score" here to keep it simple but you can keep track of pretty much any action your player makes, you could track how many questions they got wrong for example.

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

public class ScoreManager : MonoBehaviour
{
    public EventManager eventManager;

    //I'll use this as the current players score
    private Dictionary<string, int> playerValues = new Dictionary<string, int>();
    //this will be the saved High score board to compare the current players score against
    private Dictionary<string, int> highScoreValues = new Dictionary<string, int>();

    // Use this for initialization
    void Start ()
    {
        //set default score or load score from playerprefs
        playerValues.Add("Score", 0);

        //same for the highest scores
        highScoreValues.Add("HighestScore", 5);
    }

    //make sure to subscribe to the events
    private void OnEnable()
    {
        eventManager.OnCorrectAnswer += UpdateScore;
        eventManager.OnWrongAnswer += GetFinalScore;
    }

    //and also doubly make sure to unsubscribe!
    private void OnDisable()
    {
        eventManager.OnCorrectAnswer -= UpdateScore;
        eventManager.OnWrongAnswer -= GetFinalScore;
    }

    void GetFinalScore()
    {
        Debug.Log("Player's final score is " + playerValues["Score"]);

        //if the players current score is higher than the stored Highest score then
        if (playerValues["Score"] > highScoreValues["HighestScore"])
        {
            //we have a new high score 
            highScoreValues["HighestScore"] = playerValues["Score"];

            //you could add a OnNewHighScore event and trigger it here then do ui stuff like show notification, effect, etc
            //eventManager.TriggerOnNewHighScore()
            //this is in its simplest form how achievements work in games
            Debug.Log("New High Score! " + highScoreValues["HighestScore"]);
        }


        //reset player values
        playerValues["Score"] = 0;
    }

    void UpdateScore()
    {
        playerValues["Score"]++;
        Debug.Log("Correct Answer new score is " + playerValues["Score"]);
    }
}

Then in your Player Script or where ever you handle question answering trigger the relevant events if the question is correct or wrong.

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

public class Player : MonoBehaviour
{
    //you can set a refence to this via the editor or GameObject.Find/FindOfType<>
    public EventManager eventManager;


    // Update is called once per frame
    void Update ()
    {
        //Demo code when I press space it counts as correctly answering a question
        if (Input.GetKeyDown(KeyCode.Space))
        {
            eventManager.TriggerOnCorrectAnswer();
        }

        //same here but for wrong answers
        if (Input.GetKeyDown(KeyCode.F))
        {
            eventManager.TriggerOnWrongAnswer();
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. I'll try your approach as well. \$\endgroup\$ – ScottMass Jul 15 '18 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.