Search code examples
unity-game-engineunity3d-2dtools

Unity 2D: PlayerPrefs Implementation for Highscore


I need some assistance implementing a HighScore that saves. Currently, I have a score, which starts from 500,000 and gets down 150 points per seconds. This works, although when I die it still goes on, which I need to fix. I have a second kmHighscore Text, and I want it to show the highscore. Right now it shows the exact score on which I died(for example 450,875), but when I restart the game I can't seem to make it be saved. I tried with PlayerPrefs, but I am not sure how to apply it in my code. I want it to represent the lowest, in this case as it starts from 500,000, score ever achieved. Just to note: Both kmScore and kmHighscore are just numbers, I don't have text before the score or the highscore in the Unity window. Any help will be appreciated!

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

public class GameOver : MonoBehaviour {

    public GameObject gameOverScreen;
    public Text kmScore;
    public Text kmHighscore;
    float savedScore;
    bool gameOver;
    private float score = 500000;

    void Start () {
        FindObjectOfType<PlayerController>().OnPlayerDeath += OnGameOver;          
    }

    public void Update () {

        kmScore.text = GetScore().ToString("F0");

        if (gameOver)
        {
            if (Input.GetKeyDown (KeyCode.Space))
            {
                SceneManager.LoadScene(1);
            }
        }
    }


    float GetScore()
    {
        return score - (float)Time.timeSinceLevelLoad * 150;
    }


    void OnGameOver()
    {

        gameOverScreen.SetActive (true);
        kmHighscore.text = GetScore().ToString("F0");

    }
}

Solution

  • You should change your script to this:

    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    public class GameOver : MonoBehaviour {
        const string PLAYERPREFS_HIGHSCORE = "High Score";
        const int STARTING_SCORE = 500000, POINTS_PER_SECOND = 150;
        public GameObject gameOverScreen;
        public Text kmScore, kmHighscore;
        private int allTimeHighScore, actualScore;
        private bool gameOver;
    
        private void Start() {
            allTimeHighScore = PlayerPrefs.GetInt(PLAYERPREFS_HIGHSCORE, STARTING_SCORE);
            gameOver = false;
            FindObjectOfType<PlayerController>().OnPlayerDeath += OnGameOver;
            kmHighscore.text = allTimeHighScore.ToString("F0");
        }
    
        private void Update() {
            if (gameOver) {
                if (Input.GetKeyDown(KeyCode.Space)) {
                    SceneManager.LoadScene(1);
                }
            }
            else {
                kmScore.text = GetScore().ToString("F0");
            }
        }
    
        private int GetScore() {
            return actualScore = STARTING_SCORE - (int)Time.timeSinceLevelLoad * POINTS_PER_SECOND;
        }
    
        private void OnGameOver() {
            gameOverScreen.SetActive(true);
            if (allTimeHighScore > GetScore()) {
                kmHighscore.text = (allTimeHighScore = actualScore).ToString("F0");
                PlayerPrefs.SetInt(PLAYERPREFS_HIGHSCORE, allTimeHighScore);
            }
            gameOver = true;
        }
    }
    

    Couple notes about the code:

    • Never use so called "magic numbers" inside your scripts, take advantage of the const variables if those variables are immutable.
    • I added the use of gameOver since you declared it as private and it wasn't used anywhere in the class. This will stop the score counting when it's set to true.
    • Changed the score type to int, which is a better fit.