Help using

Hi,

I’m making a game where the player has to stay alive for as long as possible and the game remembers the player’s best time. However, I’m having difficulties using PlayerPrefs to store the highest time. Currently, it simply displays the time the player has survived and then resets the timer to 00:00 every time the player restarts instead of displaying the player’s best time and updating when it has been surpassed by a better time. Can someone please help me out with this?

    static float timer;
    static bool timeStarted = false;
 
    private bool gameOver;
    private bool restart;
    private int score;
 
    void Start ()
    {
        timeStarted = true;
        gameOver = false;
        restart = false;
        restartText.text = "";
        gameOverText.text = "";
        StartCoroutine (SpawnWaves ());
    }
 
    void Update ()
    {
        if (timeStarted == true) {
            timer += Time.deltaTime;
        }
        if (restart)
        {
            if (Input.GetKeyDown (KeyCode.R))
            {
                Application.LoadLevel (Application.loadedLevel);
                timer = 0;
            }
        }  
    }

    void OnGUI() {
        int minutes = Mathf.FloorToInt(timer / 60F);
        int newSeconds = Mathf.FloorToInt(timer - minutes * 60);
        int newMilliseconds = Mathf.FloorToInt(timer * 99 - newSeconds * 100);
     
        string newTime = string.Format("{0:00}:{1:00}", newSeconds, newMilliseconds);
     
        GUI.Label (new Rect(10,10,250,100), "Time: " + newTime);

        int oldSeconds = PlayerPrefs.GetInt ("hScore", newSeconds);
        int oldMilliseconds = PlayerPrefs.GetInt ("hScore", newMilliseconds);

        if (newSeconds > oldSeconds && newMilliseconds > oldMilliseconds){
        PlayerPrefs.SetInt ("hScore", newSeconds);
        PlayerPrefs.SetInt ("hScore", newMilliseconds);
        PlayerPrefs.SetString ("hScore", newTime);
        }
        GUI.Label (new Rect(Screen.width - 80,10,250,100),"Best: "+PlayerPrefs.GetString("hScore", newTime));
    }
            if (gameOver)
            {
                restartText.text = "Press 'R' for Restart";
                restart = true;
                break;
            }
        }
    }
 
    public void GameOver ()
    {
        timeStarted = false;
        gameOverText.text = "Game Over!";
        gameOver = true;
    }
}

Any help is much appreciated!

I think the problem lies in the logic of your check on line 45 - your system requires the Seconds and the Milliseconds to be higher for the time to be higher. So if the old time was 9.56 and the new time was 10.01, it would fail that check.

As a side note, I’d look at functionalizing the PlayerPrefs access so you explicitly call it when you need to update or get values, rather than it being spammed every frame in the GUI call.

1.) Look into PlayerPrefs for any variables called “highestScoreSeconds” and “highestScoreMilliSeconds”. If they already exist, then get their value. If they don’t, then create them and set them to zero.

private int highestScoreSeconds;
private int highestScoreMilliSeconds;
private int highestScoreSeconds_Old;
private int highestScoreMilliSeconds_Old;

if (PlayerPrefs.HasKey("highestScoreSeconds")) { //If "highestScoreSeconds" exist, the rest of variables will also exist because we are pushing them into PlayerPrefs accordingly
    highestScoreSeconds_Old = PlayerPrefs.GetInt("highestScoreSeconds");
    highestScoreMilliSeconds_Old = PlayerPrefs.GetInt("highestScoreMilliSeconds");
} else {
    highestScoreSeconds_Old = 0;
    highestScoreMilliSeconds_Old = 0;
}

2.) Check if your current currentScoreSeconds is higher than higherScoreSeconds, or if currentScoreMilliSeconds is higher than highestScoreMilliSeconds being currentScoreSeconds equal to higherScoreSeconds (put this into your GameOver() method, Coroutine or whatever):

if (currentScoreSeconds > highestScoreSeconds || (currentScoreMilliSeconds > highestScoreMilliseconds && currentScoreSeconds == higherScoreSeconds)) {
    Debug.Log ("Score higher!");
    highestScoreSeconds = currentScoreSeconds;
    highestScoreMilliSeconds = currentScoreMilliSeconds;
    PlayerPrefs.SetInt ("currentScoreSeconds", currentScoreSeconds);
    PlayerPrefs.SetInt ("currentScoreMilliSeconds", currentScoreMilliSeconds)
    PlayerPrefs.SetInt ("highestScoreSeconds", highestScoreSeconds);
    PlayerPrefs.SetInt ("highestScoreMilliSeconds", highestScoreMilliSeconds);
    PlayerPrefs.SetInt ("highestScoreSeconds_Old", highestScoreSeconds_Old);
    PlayerPrefs.SetInt ("highestScoreMilliSeconds_Old", highestScoreMilliSeconds_Old);
} else {
    Debug.Log ("Just some Score...");
    PlayerPrefs.SetInt ("currentScoreSeconds", currentScoreSeconds);
    PlayerPrefs.SetInt ("currentScoreMilliSeconds", currentScoreMilliSeconds)
    PlayerPrefs.SetInt ("highestScoreSeconds", highestScoreSeconds);
    PlayerPrefs.SetInt ("highestScoreMilliSeconds", highestScoreMilliSeconds);
    PlayerPrefs.SetInt ("highestScoreSeconds_Old", highestScoreSeconds_Old);
    PlayerPrefs.SetInt ("highestScoreMilliSeconds_Old", highestScoreMilliSeconds_Old);
}

3.) Finally you can create another Scene. From this Scene you will get from PlayerPrefs the scores and, in case there is a new record, let the user know and (optionally) reward her:

public class LoadScore : MonoBehaviour {
    public GameObject newRecordText;
    public GUIText thisScoreObj ;
    public GUIText thisHighScoreObj ;
    void Start() {
        int currentScoreSeconds = PlayerPrefs.GetInt ("currentScoreSeconds");
        int currentScoreMilliSeconds = PlayerPrefs.GetInt ("currentScoreMilliSeconds");
        int highScoreSeconds_Old = PlayerPrefs.GetInt ("highestScoreSeconds_Old");
        int highScoreMilliSeconds_Old = PlayerPrefs.GetInt ("highestScoreMilliSeconds_Old");
        newRecordText.SetActive (false);
        if (currentScoreSeconds > highScoreSeconds_Old || (currentScoreMilliSeconds > highScoreMilliSeconds_Old && currentScoreSeconds == highScoreSeconds_Old)) {
            newRecordText.SetActive(true);
        }
        thisScoreObj.text = "" + score;
        thisHighScoreObj.text = "" + highScoreOld;
    }
}

Hope this helps you!

1 Like

Thanks for your answer Skinner92. Currently it only displays seconds (not milliseconds) and also it simply shows the current number of seconds from zero (not the highscore). It seems like it resets the highscore every time I restart the game and thus does not remember the highscore. I’ve uploaded the full code. Could you please take a look at it? Thanks in advance!

1729236–109095–Done_GameController4.cs (4.58 KB)

I don’t have enough time to look at it as deeply as I 'd like to. I just took a quick look and found this in line 87:

if (PlayerPrefs.GetInt("currentScoreSeconds") > PlayerPrefs.GetInt("highestScoreSeconds") || (PlayerPrefs.GetInt("currentScoreMilliSeconds") >= PlayerPrefs.GetInt("highestScoreMilliSeconds") && PlayerPrefs.GetInt("currentScoreSeconds") >= PlayerPrefs.GetInt("highestScoreSeconds"))) {

Change it to:

if (PlayerPrefs.GetInt("currentScoreSeconds") > PlayerPrefs.GetInt("highestScoreSeconds") || (PlayerPrefs.GetInt("currentScoreMilliSeconds") >= PlayerPrefs.GetInt("highestScoreMilliSeconds") && PlayerPrefs.GetInt("currentScoreSeconds") == PlayerPrefs.GetInt("highestScoreSeconds"))) {

Another thing I noticed is that you don’t assign any values to these variables (why?):

public float spawnWait; //You are not setting any value here
public float startWait; //You are not setting any value here
public float waveWait; //You are not setting any value here

Have a look at it and tell me