0

I am making a game that involves the score of the player. This score is always displayed on the screen. However when i change scenes the score resets back to 0. How can i make it so that the score gets saved across all of my scenes?

I have looked on the internet for hours but i was not able to fix it that way. The 2 main things that i came across were this:

  1. Static variables

  2. DontDestroyOnLoad()

While i am sure that these would fix my issue, i have no idea how to implement them in my code. Do i make a new script? Do i put them in an existing script? And if so, which one? How can call upon variables if they are static?

Thanks in advance for any help!

3 Answers3

3

If you're just trying to be able to access simple data across screens, static variables seem like the most straightforward solution. It's fine if you've never used them before, they're very easy to use once you get used to them. :)

The first thing to do is create a class that will hold your static variables (yes, this means writing a new script and putting it in your Scripts folder). It's possible to add new static variables on a class you're already using, but if you're just learning I would recommend keeping things like that separated so it's more organized.

public class GameValues {

    public static int score { get; set; }

    // You can add other static variables here.

}

Notice I didn't inherit from MonoBehaviour. This is fine because we don't need to add this script to a GameObject, it's just going to be used to store our data. Now if we need to change or read the score, we can do it like this.

public class Example : MonoBehaviour {

    public int scoreLimit = 100;

    private void Update () {

        /* 
         * When accessing static members of a class, no object reference is needed.
         * Instead you access it as though it were a member of the class.
         */
        int currentScore = GameValues.score;

        if (Input.GetKeyDown (KeyCode.Space) && (currentScore < scoreLimit)) {

            GameValues.score += 1;

        }
    }
}

Obviously this is a rather silly example, but you get the idea. If you'd like to do some further reading, here is the official Microsoft documentation on the static keyword.

Happy coding!

matthewac95
  • 136
  • 4
  • Thanks so much, this is what i was looking for. Someone who talks to my like i am a beginner who understand barely anything, which is very much the case! :P thanks again! – Richard Batsbak Aug 24 '19 at 22:19
3

You have a couple of options.

1) PlayerPrefs

Unity has an in-built save procedure called PlayerPrefs that will store data between scenes and game restarts.

//Store Score Value
PlayerPrefs.SetInt("Score", Score);

// Retrieve Score Value if there is one
if (PlayerPrefs.HasKey("Score"))
{
    Score = PlayerPrefs.GetInt("Score");
}

PlayerPrefs Documentation

2) Unity Singleton

The Unity Singleton differs from a normal programming languages slightly in its use of DontDestroyOnLoad to keep the GameObject holding the Singleton alive between scenes.

public class UnitySingleton : MonoBehaviour
{
    public static UnitySingleton Instance { get; private set; }

    public int Score { get; set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }
}

Usage

//Store Score
UnitySingleton.Instance.Score = value;
//Retrieve Score if set otherwise (it will) return 0
Score = UnitySingleton.Instance.Score;
akaBase
  • 2,178
  • 1
  • 18
  • 31
0

Alright here's a minimal example

Save data object:

using UnityEngine;

public class SaveDataHere : MonoBehaviour {

    public string myData;

    public static string staticData = "Static data is still here";

    // Use this for initialization
    void Start () {
        DontDestroyOnLoad(this);

        myData = "I didn't get destroyed haha";

    }
}

In the new scene:

using UnityEngine;
public class InNewScene : MonoBehaviour {

    // Use this for initialization
    void Start () {
        var saveData = FindObjectOfType<SaveDataHere>();
        Debug.Log("instance data is " + saveData.myData);
        Debug.Log("static data is " + SaveDataHere.staticData);
    }
}
Ted Brownlow
  • 1,103
  • 9
  • 15
  • Thanks! What do i put in the DontDestroyOnLoad instead of "this"? – Richard Batsbak Aug 24 '19 at 21:57
  • whatever object you want to persist between scenes. If you put DontDestroyOnLoad() on the object containing your cross-scene data, you could leave it as `this` – Ted Brownlow Aug 24 '19 at 21:59
  • Okay cool! And in the second script, do i need to put anything in here: "FindObjectOfType();"? Or just leave it empty – Richard Batsbak Aug 24 '19 at 22:02
  • Well you need some way to find the object with the save data on it. Since you're loading the object from another scene, you can't link the two together from the inspector. – Ted Brownlow Aug 24 '19 at 22:29