Hi, everyone. I'm Jeremy Gibson Bond and welcome
back to the Unity Certified Programmer exam review material.
In this video, we're going to be looking at the solution
to the local save challenge that I gave you in the last video.
So let's start by looking at the DeleteSave button.
You can see here that in screen space overlay,
I'm going to hide these two panels that are on top of it and then
here in the title screen panel is the DeleteSave button.
A couple of new things here,
you can see that now,
active only during some game states has an editor only boolean,
and that means that when that is checked,
that button will appear exclusively in the Unity editor.
So, players will never see this and we don't have to worry about removing
it from our game later. Let's see how it works.
You can see here that when I click the button,
it goes to the title screen script that is attached to
the title screen panel and calls DeletesaveFile there.
Let's look at how that works.
Here we are in Visual Studio and you can see there's a new public method,
DeleteSave, and all this does is then called the
static method DeleteSave on SaveGameManager.
So, this works just like
the start game method that we used for the Start Game button before.
Now, let's take a look at the SaveGameManager.
You can see that this is a static class,
it declared on line nine.
So, this means you don't have multiple instances of it.
Just like a static field,
there's only one instance of the static class.
It can have static fields like saveFile and file path that you can see there,
as well as, the lock boolean that we'll get to in a moment.
You can also have what's called a static constructor.
On line 24, you can see the static constructor for the SaveGameManager.
This is called the first time any script references
SaveGameManager and it sets up our static class instance.
So, it initially sets the lock to false.
This lock boolean will stop us from saving the file when it is locked.
This allows us to do things in loading
a file that might normally cause a save to happen and it stops the save from happening.
It's just a way of protecting us from messing up the integrity of our saveFile.
Then I set the file path which is this persistent datapath plus AsteraX.save.
So, AsteraX.save is just the name of our file,
but this application that persistent data path
is valid on all the platforms we're going to
use and it is a hidden place locally that Unity can saveFiles on the device.
This is better than PlayerPrefs now
because a lot of players have figured out how to hack PlayerPrefs and
this gives us a little bit more secure place to put
things and because we have direct control over what we write into the saveFile,
you can encrypt it, you can do all sorts of things,
whatever you want to make it as secure as you can.
Then you've got my first instance of DEBUG_VerboseConsoleLogging.
So, I have this turned on now and what this does
is it just gives me more information about what's
going on with the saveFile while in developing and then as with a lot of these things,
I can just comment it out at the top and then it will not be
defined in all of these lines in between the if and inif,
will be commented out and will disappear from
my script so that I don't have to have all of
these debug messages popping up all the time.
The final thing that I do in the constructor is I create
an instance of the saveFile class and I store it in the static field saveFile.
Let's go take a look at that class here you can see the definition of
the saveFile class at the bottom of
the SaveGameManager script and it's a pretty straightforward class.
It has arrays for StepRecords and achievements that just duplicate those arrays in
the achievement manager and then it has an integer to store
the highScore and it has a base highScore of 5,000.
Now, let's look at how that high score is managed.
You can see here that I'm in the AsteraX script in the addScore method.
This is the one that gets called whenever we say shoot an asteroid.
So if you shot a small asteroid which is worth 400 points,
then AddScore would be called with the number 400.
It goes through and adds the score like normal and then on line 573,
we say if we have not already gotten a high score in this game,
and we check the highScore in
the SaveGameManager and it is higher than our current high score,
then set GOT_HIGH_SCORE to true and show a pop-up about it.
So, let's go back to the SaveGameManager and look at CheckHighScore.
You can see that this just says,
if the score that was passed in is greater than the saved high score,
set saveFile to highScore to the new score and return true.
Otherwise, return false.
Back here in the AsteraX script,
you can see that we only check for a high score until we
know that we've gotten the high score and then once GOT_HIGH_SCORE is set to true,
we don't check anymore.
This is to prevent us from constantly
checking and constantly updating and things like that.
So, I'll show you how we manage getting the final score in a moment.
But first, I wanted to talk about this AchievementPopUp.ShowPopUp.
This is a new static method on AchievementPopUp that allows us to cause
that drop down to happen anytime we want and it's very straightforward.
You can see here in the AchievementPopUp script that
ShowPopUp just takes an achievementName and an achievementDescription
which is respectively the top line and the bottom line of that pop up and then it
calls the singleton S.PopUp and passes those in.
So this is a way of using the AchievementPopUp
without passing in an actual achievement or having a reference to it.
So it makes it able to be used in several different ways in our game if we want to.
Going back to AsteraX,
I talked about how I'd handle actually getting the high score when the game is over,
and that is exactly it.
We wait until the game is over and then as part of our GameOver,
we check for the highScore and pass in
the final score in the game which is going to take the highest score in
the saveFile and up it to
the actual highScore and then we call SaveGameManager.Save to save the file,
and here is that save method inside of the static SaveGameManager class.
So you can see that if the class is locked, I return immediately.
So I do not save if I've lock set to true.
But if lock is not set to true,
I pull the stepRecords and the achievements from the AchievementManager,
then I pass that instance of the saveFile class into JsonUtility.ToJson.
With a second parameter of true,
this converts the saveFile from a class into
JSON text into a string and the true is pretty print.
So that makes it to where it's easier for a human to read.
After converting to a JSON string,
we then write that string to the filePath that we
recorded earlier using the File.WriteAllText method
and it is line six using system.IO that allows us
to access the file class and write to files.
Finally, if we had the VerboseConsoleLogging turned on,
we will spit out both the filePath and the JSONSaveFile text to the console in Unity.
So, we can see what's going on.
So, let's take a look at that right now.
If you're following along,
remember to re-enable the Level AdvancePanel and the GameOverPanel.
Otherwise, you'll run into some errors.
So now, I'm going to save my scene and I'm going to press
play and then I'm going to
click DeleteSave which will wipe out my saveFile and click Start.