Saving a highscore over a span of
several game sessions is very easy and can be done using Unitys PlayerPrefs.
In this tutorial I will show you how to save a simple point value and how to show
this value in your UI as a highscore.
There will also be another part where I
show you how to handle a list of highscores together with the names of players, you know like
it was popular before everyone had internet.
Now let's start. Currently our points increase
every second while in playmode. To define a start and end point I'll add two buttons. One which will
start the game and therefore the point counter and one for the end. This will end the
counting and check for a new highscore.
I create an empty object as a wrapper for
the button and place it at the bottom.
To your wrapper, the parent element of your
buttons you can add a "Horizontal Layout Group", which will set the childrens position. I'll
change the alignment to "Middle Center" and the buttons will now be equally spreaded.
For the button handling I add a scipt called GameHandler. In there I define two public
methods, which will be used from the buttons. In here That's fine for now.
Inside the PointCounter script we created in the first episode,
I rename the default Start method to StartGame. So the point counting won't start on game start
anymore but rather when this method is called.
I add a StopGame method like in the previous
script and a boolean I call "gameStopped". This will be the new condition for our while
loop, as long as this value is false, the loop will go on.
Inside the StopGame method I will set this boolean to true and therefore
the while loop with its counting will stop.
Now let's complete the GameHandler. At first
I need a reference to our PointCounter script. At this point a Singleton would be really
handy, but since we keep this simple I add a serialized field, so that we can
add the reference via the inspector.
Now in the StartGame and the StopGame
methods we can call the newly created methods from the PointCounter script.
Do this for both of your buttons.
Back in Unity make sure to add your
GameHandler script to your scene, like I did with this Manager-Object and also fill
the reference. Now inside our buttons I add the onClick event. Drag and Drop the Object
where your GameHandler script is located down into the object slot. Now look for your
script name and in there your method name.
When I now test the game, you can see that
I can start the game and then stop it. In this case 40 would be our highscore, so
let's implement the fun stuff now.
At first we need some UI. I add an empty game
object as wrapper and move it to the top left. To make sure everyone knows that this will be
the highscore I also add some text. I duplicate the text object and add an example number
for our real highscore number value.
Again if you add a "Horizontal Layout Group" to
the wrapper, your elements will be placed next to each other. I change the alignment to the
center. If you want to get rid of the spacing between those two, you just need to disable the
"Child Force Expand" checkbox in "Width".
For a highscore way to small, let me increase the
size a little bit more. Now that's not bad.
So, again like in the Point Counting
Tutorials I'll separate the logic from the UI. I create a new script which will be
responsible for storing and updating the current highscore value if there is a new one.
A simple integer will always represent the current active highscore. Inside the default
Start method I will call another method which is responsible for setting the
latest highscore from the saved ones.
We are going to use the PlayerPrefs
for this simple value.
"PlayerPrefs" is a class that stores Player
preferences between game sessions. It can store string, float and integer values
into the user’s platform registry.
So. you can easily store simple key-value pairs
in your playerprefs which will then be stored inside of your OS Registry. For complex
cases this approach is not recommended. But for now, let's got with this.
With the "GetInt" method we will get an integer with the key-name "Highscore". If
this is empty we want a default value of zero. I save the response in our highscore variable.
I create a new method called "SaveHighscore". This will simply save the highscore
integer variable to the PlayerPrefs. Therefore we use the "SetInt" Method and use the
exact same name like above in our "GetInt"-Call. So the key must match. In this case the second
parameter is the value we want to set. Instead of using the variable we definied at the top of
our class, I use a parameter for this method. This makes this method more flexible and you don't
have to be extra careful to only call this one after replacing the highscore
variable with the new value.
Now we need a public method, which will
be called whenever our game has ended and there could be a new highscore. It's up to this
HighscoreHandler to check if the reached value is a new highscore or not. As parameter
there will be the reached score.
We will check if the reached score is
greater than our current highscore. If it is, we will replace the highscore variable
with the new one. To make sure the new value will be saved, we also need to call the SaveHighscore
method and add the current score as parameter.
And don't forget to call the
"SetLatestHighscore" method in the Start method. This will set the initial value.
Great, now we just need to call the "SetHighscoreIfGreater" method
whenever our game ended. So let's switch to the GameHandler.
Here we need two new references to other scripts. Of course we need the HighscoreHandler script,
because this is where we call the method. But in this case we also need a reference to
the PointHUD script, because this is where our current point value is saved, which we will
then pass to the highscore validation method.
In the StopGame method we can now add this
function call. As parameter I'll use this public Point getter from the pointHUD script.
We created this earlier in this tutorial series, so if you made anything different,
make sure to add the correct reference to your point value.
Great, now we can test this.
Add your new script to your manager
object and set all the references.
Unfortunately we won't see anything,
because we didn't implement the UI yet, but this won't stop us. Inside your inspector,
where your Highscore Handler script is located, just click at those three dots and select "Debug". This will make our highscore integer
variable visible even if it is private.
Let's start the game. You can see, nothing happens
to the variable, which is what we want. But when we stop the game, the current highscore of zero
gets replaced with the new highscore of 35.
When I now stop the playmode and then start it
again, you can see it will initially set the 35. So the saving inside the
PlayerPrefs also works nicely. If the reached points are lower than the
highscore, it won't be overwritten.
Our main logic works, great. Now we can
add the UI handling inside a new script.
I create one and call it "HighscoreUI".
Like we did in the PointHUD script, I
add a reference to the Text component from the highscore. Make sure to add the
UnityEngine.UI package at the top.
I then add a public method, which is
responsible to overwrite the UI text with the parameter value. Just change the text
of your text-variable to the score variable and convert it to a string with the "ToString" method
of integers. There's not much more to do here.
Now we just need to call this method
whenever a new highscore get applied inside the HighscoreHandler. Of course at
first we need a reference to this script.
After we set a new highscore successfully, we will call the "SetHighscore" method
with the current score as parameter. But we also need to call this initially,
after the load of the saved highscore.
Now this would become a bit messy.
Let's improve it. I add a setter for the highscore integer variable. Whenever this
setter is called we can now update the UI. Since the setter is public I named it like
our variable but with a capital first letter.
Now just replace every assignment to the
highscore variable with the new setter, with the capital first letter. We used this
approach also for our points. Now whenever the highscore setter is called we will save the
updated value. This is very well maintainable especially for future changes in your code.
So now we just need to add this
script to our Manager Object and assign all the references. Make sure to
add the correct "Text" component as well.
And now let's test it. You can see, the highscore
number was just updated to the 35 we had earlier. I stopped the game on 45 and the highscore
value gets updated immediately. That's it.
The HighscoreUI script looks still empty now,
but since we divided logic and UI you can fill this with some cool animations and you don't have
to touch your highscore saving logic anymore.
In the next episode I'll show you how to create,
update and save a list of highscores with their player names. This is far more complex, because
we are going to store the data as a JSON. So there will be a tutorial about this beforehand.
Thank you for watching. If you enjoyed the content, consider liking and
subscribing and I'll see you next time.