In the last lecture, we turned our audio player into a singleton so that when we changed our scene,
the music would continue to play.
And during that lecture, I also asked you to think about some other objects that may benefit from being
a singleton.
So hopefully you had a good think about that question.
And there were a couple of different answers depending on the approach you're taking.
One valid option is that nothing should be a singleton and there are better or different ways of approaching
our code to make sure we don't use them.
But assuming we do want add some singletons to make our life a little bit easier, the first candidate
would be our level manager because we've got one of these in every single scene.
They're all doing exactly the same thing and we only ever really want one of them at any given time.
But since having multiple level managers in a scene is not really going to break anything, it's not
essential that only one ever exists at a time.
The only real benefit I can see from making this a singleton is if we make it a pure singleton and have
global accessibility.
So we only ever have one in our entire game because we can then stop worrying about this scene.
Loaded delay in our hierarchy.
Because if we change this in our main menu, it's not going to translate over into our game scene at
the moment.
So we could potentially change things in the wrong place and it will become a bit of a nightmare.
But for now, the way I said we can get around this is just to remember or add a tooltip maybe to our
script to tell us not to edit this in our same view and instead only change it on the prefab version.
So as long as we haven't overridden it somewhere, it should update everywhere.
Turning our level manager into a singleton would also create some other problems that we would need
to solve, like how our canvas buttons are currently linked up to our level manager.
So if we start moving that between scenes, we're going to have to have a script attached to our canvases
to allow our buttons to find the level manager that's in the scene at a given time and then hook themselves
up.
So it's going to create more work than we really want to do.
So let's leave our level manager alone because it is working perfectly fine as is.
But the other candidate for a singleton, which I think we will pursue, is going to be our scorekeeper
because we currently have a scorekeeper in our game scene for tracking our actual score during play
and our game overseeing for displaying the score at the end.
Our scorekeeper needs a way of transferring that score from one scene to another, so it would make
sense if the same object got carried across.
And we also want to make sure we don't end up with more than one scorekeeper in a scene.
If we ended up with two or three scorekeepers in our game scene, then every time we scored points,
we'd be scoring triple the points.
So our scorekeeper is going to make a good single turn, I think.
But before we go ahead and set up our script, let's just do a little bit of extra work on our canvas
so that we can find our score, text and update it.
So over on our canvas we're going to add a new script.
So over in our script folder, let's right click create a new C-sharp script, and I think we'll call
this one the UI game over.
Let's track that onto the canvas and then open it up.
And if you fancy a bit of a mini challenge, then go ahead and write this script completely on your
own and I'll give you a moment to pause the video if you want to do that.
Okay.
So if you did this as a mini challenge, very well done.
Or if you want to follow along, that's absolutely fine as well.
So let's first of all get rid of our update method because we're not going to need it.
We will need to start.
But let's clear off our comment and we're going to want to connect this script up to the text mesh pro
element on the canvas.
So the top of the script, we're going to include a new using statement and we're going to be using
TM Pro.
Then let's create a serialized field for our text mesh, pro-EU Gooey Element and call this the score
text.
Let's also grab a reference to our scorekeeper and call this the scorekeeper.
And then in a wake, let's set our scorekeeper to find objective type scorekeeper.
Finally, let's set our score text in start so we can say score text.
Text is equal to our scorekeeper.
Don't get score.
Now this is returning an integer, so we're going to need to turn it into text.
We can do that like we did in our game scene by just adding the two string method.
But if you remember back over on our canvas, we also have this.
You scored part of the scoring message.
So we can actually do away with this two string method if we want, because when we start concatenating
strings and integers, the whole thing will get treated as a string.
So let's add our little message of you scored.
And to place our score on a new line, we can just use the new line character.
So let's save this up and jump back over into unity over on our canvas.
Let's take our UI, game over script and drag over the score text.
And if we hit play now, we should have a message of you scored zero.
So that seems to be working.
And the next step is going to be to convert our scorekeeper into a singleton.
And this is going to be your challenge.
I want you to turn our scorekeeper into a singleton.
So if you feel up to taking on that challenge without any further advice, then go ahead and pause the
video now.
But if you want a hint, then take a look at what we did in our audio player for reference, because
this is going to come in very handy for you.
So pause the video now and give that a go.
Okay.
Welcome back.
So to set this up as a singleton, let's take a look at what we did for our audio player.
We had a static audio player instance and then in a wake we were calling our managed singleton method.
This method was checking whether our instance was null.
So if we weren't the first object to come along, then we were going to get destroyed.
Otherwise, if we were the first ones to come along, then we're going to set the instance to this version
of our audio player.
So let's actually copy all of this.
So our static variable, our awake method and our manage singleton method, and then over in our scorekeeper,
let's just copy and paste that into our code and pretty much all of it can stay as it is.
The only thing we're getting an error on is when we try and set our instance to this, because we're
trying to set a scorekeeper into an audio player, which definitely isn't going to work.
So instead for our scorekeeper we need a static scorekeeper instance.
This will then get rid of our red error and everything should work as expected.
So let's save up our script and jump back into unity.
And if we go ahead and hit play, we should find that our score initially gets set to zero, which it
does.
And when we play again, our score is zero.
But if we rack up some score before we die, so let's just get a couple of points.
100 is fine before we die.
This hundred now gets carried over to our score.
But we've now got a secondary problem that if we play again, we start off with a score of 100.
So our next step is to work out when and where we want to call our reset score method.
Well, if we head over to our script and open up our level manager, it would be a good idea to reset
our score whenever we load our main gain.
So this script is going to require a scorekeeper called scorekeeper.
And then in awake we need to find this scorekeeper.
So avoid awake scorekeeper equals find objective type scorekeeper.
And I'm sure all of this finding stuff in awake over and over again is really starting to tempt you
into that public and globally accessible singleton pattern that we looked at last time.
But with that set up, then let's go into our load game and before we load the scene we want to say
scorekeeper dot reset score.
So whenever we load into our main game, our score will now be reset.
So let's save all of our scripts and jump back into Unity one last time for some testing.
Let's go ahead and hit play and we're on the game over screen at the moment.
So our score is zero.
But if we play again and rack up some points, we don't need to rack up many.
We really just need the minimum amount of 50.
Our score is transferred over, but if we play again, our score gets reset.
And we thought, I think our game is pretty much there.
We have a nice gameplay loop which we created with our different menus.
Our score is nicely transitioning across from our different scenes and being reset at the right time.
Our audio player is playing our music consistently through our levels, and really the only thing left
to do is to add some more content.
So more waves, more enemies, more explosions, playtest our game and finally build our game so that
other people can play it.
So congratulations on getting everything working and we'll talk about some play testing and balancing
in the next lecture.
So I'll see you there.