[Music]
hello everyone welcome to this video on
making a tower defense game in unity
today we are going to have a look at
unlocking levels but Before we jump into
unity and get started I just have a few
things that I wanted to address the
first one being I am now on a fixed
video schedule that means every
Wednesday and Sunday that's Wednesday
and Sunday I'll be uploading a new
tutorial I've actually been on the
schedule for quite a while but for some
reason I just haven't really told it to
you in a video and yeah no particular
reason why I'm just a doofus and the
second thing is I got a new camera and
I've been experimenting a bit with kind
of the layout and setup for these
tutorials so let me know what you think
of this new setup and yeah please be
constructive about it but I definitely
want to hear what you guys have to say
so that I can fine-tune it because I'm
still figuring out some of this stuff
and that's also the reason why this
particular video is uploaded on Thursday
and not a Wednesday is because I messed
up something with the new camera it's
pretty embarrassing but I shouldn't have
nice stuff so yeah I had to postpone it
a single day oh and I forgot to mention
that this previous weekend was Ludum
dare a which is an awesome game
development competition where you get 48
hours to make a game from scratch using
only code and assets that you create
yourself I participated and you can find
my submission in the link in the
description so check that out if you
want and definitely expect a
behind-the-scenes video as soon as I can
get that done so yeah let's jump into
unity so let's get started by opening up
our level select scene and also our
level selector script so just double
click that and it will boot up in Visual
Studio and here you can see we simply
have a reference to our fredo script
which is responsible for changing scenes
smoothly and we also have our public
void select and that's currently just
called by the different buttons but our
script has no reference to the buttons
in our scene it doesn't know what they
are they simply call this function so
let's start by creating a list or more
specifically an array of all of the
buttons that we currently use in order
to be able to change to a certain level
so to do that let's create
of course a public variable and we need
these to be of type button but that's
not included by default we need to go up
here and say using unity engine dot UI
and now we have access to the button
class then we can call the button array
here and we need to mark it as an array
by opening and closing these square
parentheses we can call this one our
level buttons now when we save this and
head back into unity and when we then
select our level selector object with
our script we should see a new array
that we can resize more specifically we
can add two new elements and of course
we want to add our two buttons here so
let's just find that those under the
scroll rect under the content and we
have our first level button and our
second level button and we'll just drag
those in so what this allows us to do is
now in our script at any point let's
just choose the start method here so
right when we boot up this scene what we
want to do is loop through all of our
buttons so we want to go for and
whenever you create a for statement you
could go ahead and type it out yourself
so far in I equals 0 we want to go as
long as I is less than level buttons dot
length but this is always a bit
redundant what we'll do instead is just
write for and then tab tab and that's
going to automatically insert all of
this stuff forth so we can name our
variable we could call it J for example
but we'll just call it I and we'll also
change the length here to level buttons
length and this way we quickly have a
for loop that will go through and for
each button in our array up here we'll
create a variable I with the index of
that button so we'll just keep going
until we reach the end of our array and
what this allows us to do is now say
level buttons to the ith element so
which is the first time we go through
it's going to select the first button
which has an index of 0 the second time
it's going to select the second button
which has an index of 1 and of course
it's going to stop there for us but you
can have an unlimited or
at least a pretty long list of buttons
on here and it's not going to complain
about it and then we can go dot
interactable and we can then disable the
interact ability of these buttons so
this really does through script is go to
our button and then disables the
interact ability here so it just toggles
off this switch right here and of course
we do that for both buttons right now so
if we go and hit play we should see that
we don't see any hover animation and
that we cannot actually click these
buttons what a standard button will do
just a default one is because it uses
the colored tint as a transition we'll
go ahead and maybe fade out the button a
little bit so it's clear that you cannot
interact with it but we don't do that at
the moment so let's instead go in and
create a small animation just like we
have the normal highlighted and pressed
we also want to go and do something for
the disabled and what we want to do with
this animation is simply find our color
and then drag down the Alpha quite a bit
just to make it very very clear that
this button is not to be interacted with
but remember whenever we change a
parameter on one of the animations we
have to make sure that it goes back if
we then re-enable it we don't want it to
just change its alpha and if it then
goes back to normal it will stay at that
alpha and we of course have to input a
keyframe here for the color as well
where the Alpha is 255 so we'll just go
ahead and duplicate this keyframe here
and paste that on the highlighted as
well and undepressed so it's only when
it's disabled that we will get this on
faded color and we can do this on one of
the objects only and we don't even even
have to do any applying of the prefab
because they all share the same
animation files and that's what we've
just edited we just edited right now
this button here that has the disabled
highlighted normal and pressed cool so
what we should now see is that when we
hit play they're both faded out and
that's awesome one thing that we of
course do not want to happen is that
right now both of these buttons are
faded out
and we want to always be able to choose
at least one so of course we have to
keep track of what level we're currently
reached and in order to do this um it's
not enough to just ah create a variable
because a variable won't persist between
scenes if we create the same script in
the first scene and in the second scene
it's not going to carry over if we mark
it as a public static variable that is
totally going to work and it's going to
carry over but as soon as you close down
the game your progress is going to be
lost and the static variable is just
going to go back to its default value so
what we do instead is save our progress
to some kind of file many advanced games
use some kind of data format for this
and that could be JSON or XML which are
basically just formats for storing loads
of data say you want to store
playerhealth player progress levels all
that stuff maybe even where objects are
placed in the scene where your player is
in the world when he locks out stuff
like that you can store a lot of stuff
in those formats and you can definitely
check that out
it's called serialization but what we do
which is a lot easier and it's something
that unity has provided us for this use
case specifically is use the built-in
player preps and this just allows us to
store either is string a float or an
integer and you can store multiple
integers multiple floats multiple
strings so you can actually use it for a
lot of stuff really really easily so
what we do in order to utilize this
function is let's create a new variable
and let's call it level reached this is
going to be the level of the highest
number that we have reached so in the
beginning this is going to say 1 then
when we beat that level we get to go to
level 2 so we level reached will be 2
and so on so we don't want to set this
equal to either 1 or 2 instead we want
to set it equal to the level that we
have reached and therefore we go to
player prefs and you use this whenever
you want to get a value or
setup value and then we do dot and in
this case we want to get a value so we
go get and then you can see we have both
string in and float in an our case
because it's a limited amount of levels
we want to just use the integer some
number some whole number so let's use
get int and then we give it the name of
the key and the key is basically just a
string value that you used to associate
with that number it's basically the same
thing as a variable name so if we treat
this integer as a variable that has a
value and the key to get that value is
the name this uses the exact same thing
so our key here could be the exact same
level reached and I think we should just
do that for simplicity we also get to
specify a default number so in our case
we do comma one and that's because we
want our default level reached to be one
we do this so that if we have never
played the game before and it tries to
go here and find a saved piece of data
called level reached and it isn't
created yet it's just going to return
the value one and so it's only going to
allow us to play the first level this is
going to happen every time a new player
plays the game so now we can use this
level reached in order to specify what
level buttons we want to actually be
interactable and we do that by saying
that if the current value of our I here
so if I which means the index of the
button we are currently on is less than
level reached well then we want to go
ahead and make it not interactable so if
we haven't reached that level yet if
this current button has a level index
that we haven't reached we want to go
ahead and make it non interactable but
of course our eye here starts zero and
obviously our level reached starts at
one so we have to just add one on to the
eye in order to make that totally valid
whoops I noticed a bug here that we have
to fix before we run this and that is if
I plus one is grew
rather than the level that we reached
then we want to disable it awesome so we
can save that hidden to unity and what
we should see now is that when we play
the game it's not going to have any
previously stored data and so it's just
going to return one and that means that
the only button that's going to be
clickable is the first one and the
second one should be grayed out so if we
play now we should see exactly that
happening and that's awesome and again
we cannot click this but we can proceed
to the first level so that's actually
all we need to do for a level selector
but of course we still have to change
our level reach so that we can actually
progress in the game it's not going to
do that automatically so what we do here
is head into our first level we find our
game master so let's find the place in
our code where our level ends and that's
inside of our wave spawner so let's
double click that and scroll down here
to where inside of our spawn wave we
realize that we've just spawned all of
the waves that we wanted to have in this
level we currently just throw out a
debug deadlock statement saying that we
won the level and then we disabled this
script what we want to do instead is we
probably still want to throw out a debug
block and you might even display some
cool information here like the amount of
waves that you just went through and the
amount of enemies you killed cash earned
stuff like that but what we will also do
is of course increased the level reached
so in order to do all of this stuff I
don't want to do it inside the wave
spawner I want a more appropriate place
to put this code and that is of course
inside of our game manager this is
responsible for ending a game and so I
think it should also be responsible for
winning a level so that's going to and
create a public void and let's call this
one something like level 1 or you could
just put win level which I think we are
going to put and enough in here we could
throw stuff like a debug deadlock
statement and I think we're just going
to copy paste that in there so we know
what is going on and of course we need
now a reference to the game manager
inside of a wave spawn in order to call
that function
let's go to the top here and let's
create a public game manager and we're
going to call it a game manager as well
let's go down here and say game manager
dot and then we call win level then
inside of our win level script we threw
out the debug deadlock we could then go
in here and say player prefs
dot and now we don't want to use get now
we want to use set so we use set in and
again we input a key which is the name
of our value so our name is level
reached and it's very important that you
type this the exact same way that you
did inside of the level selector it's
not going to throw an error if you
didn't so just go in here copy this
paste it in here and you're good to go
just make sure that that's correct
because it's not going to complain about
it if you make a mistake and then we
throw a value and the value here could
be in our case we want to transition to
two if it's the first level and to three
if it's the second and so this is
something that will dynamically change
one thing you could do is keep sort of
an array a list of all of the different
levels with an Associated index that you
put in here that would be totally fine
or you could at the top here inside the
game manager have some variable let's
start with a public string and this is
going to be the name of the next level
and we'll just default that to level two
and we'll also have a public integer
which is going to be the next level
index or we could call it level to reach
or let's say unlock and we can default
that to two as well so this is a bit
more fragile because you'll have to
remember to write everything in there
but you will have to add it to the level
array anyways and it's just a lot easier
so now we simply input level to unlock
in here and then we want to actually
change the scene
we of course need another reference
that to our fate script so we'll go up
here and get again and we'll create a
public screen or on scene fader and
we'll call this one scene fader and now
we can go down here and type scene fader
f82 and the scene that we want to fade
to is the next level awesome so that
should actually work just fine so now we
just need to go into our game master and
we need to input this new information we
need to drag the game monster or manager
inside of the wave spawner scheme
manager there we go so that's linked up
we want to drag the scene fader into our
game manager and we want to confirm that
our next level is level 2 that's correct
because we're currently on level 1 and
the level 2 unlock is also to come
that's also correct so now we can just
save this and it should work right away
so let's go to our level select let's
hit play and we should now be able to go
to the first level here and run through
it but that's going to take some time so
I thought we would just take a shortcut
which means just loading up level 1 and
finding our wave spawner and setting the
time between wave to 0 just so it it
will really really quickly run through
here so let's just put in a lot of
objects or game objects here to kill off
the different waves as they spawn
awesome so you can see how quickly that
win and you also notice the bug but it
transitioned to the second level here so
let's focus on that and we'll fix the
bug in a second so it turns second
decision to the second level and now we
can go and choose our level select again
and we can just hit don't save on that
we don't need to do that hit play and
you can see that they are both unlocked
so that's awesome and it's going to keep
doing that if we create say if we just
very quickly go in here and create
another button so just duplicate level
button too and we change the text here
to 3 and we go into a level selector and
add it to the array so we'll go 3 there
add it in there and
play you should see that that's not
unlocked and indeed it is not so you can
see how easy it is now to add new levels
to this system so now let's just focus
on our bug and we'll call that a day so
let's go into our first level here and
basically what happened is it marked on
the level here as completed before we
had actually destroyed all the enemies
and it even went on to spawn a wave
before a previous wave was completed and
the reason why is because of the way
that we are currently checking if a way
wave is done and we do that by if we go
into the wave spawning here each time we
spawn an enemy we increase enemies alive
by one and then when we kill an enemy if
we find our enemies script so we'll go
and double click on the enemy here every
time we die we decrease enemies alive
and if enemies alive reaches zero it's
going to go ahead and spawn the next
wave but the problem with this the
problem with this is that we of course
instantiate the enemies with a bit of
delay in between them so we don't just
go ahead and spawn all of the enemies at
the same time you can see here that we
wait the wave rate so one divided by the
wait rate and therefore there's a bit of
delay between each enemies spawn so if
an enemy spawns and we destroy it before
the next one
the amount of enemies alive is going to
be zero in the middle of the REA wave
and if we're unlucky it's going to start
the next one or transition to the new
level so in order to fix this instead of
increasing enemies alive when we are
spawning enemies we're just going to set
enemies alive equal to wave dot count
before we actually start spawning so
this way we'll just set the enemies
alive to the amount of enemies that are
going to be spawned and yeah just use
that it's much simpler
and it should work much better so if
we're now go in here and set out time
between wave to something like one let's
just decrease it a little bit and we'll
very quickly just run through this so
let's create a bunch of turrets to take
care of our enemies and we'll create
some of higher level as well let's use
the laser beam here you can see that the
previous wave does not start until
you've actually completed the or the
next wave doesn't start until you've
completed the previous one and once we
get through the last wave it's going to
transition so now that bug should be
gone awesome so you will notice a slight
disadvantage when it comes to just
duplicating levels like this and that is
all of the changes that we've made to
our game master in here have not updated
in level two you still have to set up
the scene fader and game manager in
level two what we can do since we don't
have anything special going on in level
two is just delete that and then
reduplicate the level but of course
that's not super awesome if you have a
lot of stuff going on that is different
between the two levels what I would then
recommend is you can of course go ahead
and make all of these different objects
into prefabs that you just make sure to
update whenever you change them and you
can get really far using that method but
if you are really serious about this and
want to create a lot of different levels
what I would recommend is you utilize
the fact that unity has now created a
way of loading different scenes in you
create one scene for all of the stuff
that is shared between all the scenes
like the game master and the scene fader
the node UI stuff like that that doesn't
necessarily need to be interlinked with
the actual layout of the level and then
you have another scene which is odd
which is different for each level which
is the actual layout of the scene so
that's something that you might take
into consideration if you want me to
show kind of how that's done of course
let me know I think next up is probably
some screen that will display in order
to show how you did in the level I think
that's pretty important instead of just
going directly to the next one but that
was pretty much all I wanted to show you
in this
video and I will see you in the next one
thanks to have the awesome patreon
supporters who donated in November and a
special thank to sultan al sharif by
samara fire james Calhoun and Robert
Bonham become a patron yourself at
patreon.com slash practice