Transcripts
1. Introduction: Hello everyone and welcome to the Unity Mobile Game
Development course. As you can see, we will learn through this Space Shooter example game It's created with the
new input system. But before getting into details, note that with this course you will also get some
general knowledge and techniques
that you can apply to other types of mobile games. E.g. we will learn how to
implement three types of ads. One example is Rewarded ads,
when a player loses the game, he can watch one unskippable
ad and continue to play. Another example is skippable ads that can appear between levels. And we control how often
they will appear. We will also learn how to send notifications for
Android and iOS devices. There is a level selection with a simple unlocking system. As
the player wins one level, the next will unlock. For each level, we track scores and high scores. We learn how to
create a loading screen, which of course you can
use in any game type. All levels have scrolling backgrounds and spawners that can spawn
different types of enemies. The player can pick
up some power-ups like shield and
shooting improvements. It's possible to lose the shooting upgrade
when taking damage. It wouldn't be fun
without some boss fight. So we implement Boss
at the end of a level. Optimization is an
important part. So we'll learn a little bit
about Scriptable objects, how to use Profiler to
detect possible problems, And we use Unity's new
object polling system. We learn how to
test games on phones, both Android and iPhone. In the end, we fill
out all the forms on Google Play and go through
the publishing process. There is a lot of
content that I didn't manage to mention in
this short introduction. But if you find any
of this interesting, enroll today and see
you in the course.
2. Create a project and choose settings: Hello everyone. Welcome to the mobile
space shooter course. To start with the course, Let's choose optimal
project settings. So first open your Unity
Hub and go to instance. Here you can find all installed Unity
versions on your PC. I will use the unit in 2022
version for this course. So the best way to
follow this course is to use any 2022 or newer version. Also, make sure that you have Android or iOS
modules installed. To install modules for the
Unity version you need click on the Settings
button and add modules, then choose Android
or iOS or both, and continue with
the installation. As you can see, I already have modules for the 2022 version. Now go to projects.
New projects. First, select the Unity version. Then you can see some
project templates. You can see there are 2D
and 3D mobile templates. These templates come
with a bunch of packages that you need
for mobile games, but often you will
not use them all. So instead, I prefer
to create basic 2D or 3D projects and then manually input packages that
I'm sure I will use. This is a 2D game. So select the 2D basic template and choose a name
and a location. Then we can create a project. You should see
something like this. The first thing we need
to do is to switch the target platform
to Android or iOS. So go to File build settings. By default, the target platform is Windows, Mac, and Linux. This is a mobile game, so I will select Android and
click on Switch Platform. Wait a moment for
unity to do the job. Nice. This is a basic project setup. In the next video, we'll explore a very useful feature
Device Simulator. See you in the next lecture.
3. Device Simulator: Hello everyone. After the basic project setup, let's explore
another cool feature that will help us
develop a mobile game. It's a device simulator. To open it, select
the game window, expand the list, and here you can switch to the
simulator window. You can also find
it if you go to Window general and
device simulator, the simulator will show you
how the game will look on a certain device and you can test gameplay with the mouse. If you expand the device list, you can see a couple of
devices that you can select. I recommend that you
install additional devices. It will give you a lot more
options to choose from. Of course, you can play
with some settings. You can scale the view
or choose fit to screen. You can rotate the screen. And this safe area is for the
navigation of UI elements. Feel free to choose
the device you want. I will go with Samsung
Galaxy S 105 G. Now, when everything is in place, in the next video, we will import project assets
and slice some sprites. See you there.
4. Sprite Importing and Sprite Editor: Hello everyone. Let's continue with the course
and input some sprites. Organization over the
workspace is very important. So let's create a new
folder for sprites. Make sure you select
the asset folder. Right-click Create folder. I will call it sprites. Open it. Now, you can download this
price from the resources. Use some tools like when
there are two extract files. As you can see, sprites
are organized in folders. Select them and drag
them into the project. Feel free to explore sprites. For now, let's select
the player sprite. In the inspector window, we can see sprite settings. Let's expand this
part at the bottom to get a better preview of
the selected sprite. For most sprites encoding these default settings are good. We don't need to
change anything. We can select the scene view and plays the
sprite in the game. However, some sprites
need changes, e.g. in the enemies folder, we have two enemies
in one sprite. We need a way to slice this
sprite into two parts. So select the sprite, change sprite mode from
single to multiple. Then go to the Sprite
Editor and apply changes. In the Sprite Editor. In this case, sprites might appear a bit blurry,
but don't worry, that's because they are
upscaled for preview, because it's a mobile game. Usually dimensions are small as possible to optimize
performance. To slice, sprites go to slice, choose grid by cell size. I know that one cell size for
this sprite is 128 pixels. How do I know that
in this project, every spread has dimensions
included in the name, e.g. this sprite is
named enemies 128. So if you make your own sprites
or you hire some artists, make sure that you know
the precise dimensions of the sprite and grid. I like to place
dimensions in names. Okay, set pixel size
to 128 for x and y. Click Slice. You can see two separate cells, each containing one enemy. Apply changes and exit
the Sprite Editor. We can delete the
previous object. Now, when you expand the sprite, we can use each
enemy separately. Another example is
this explosion effect. We need to slice it. Also in the Inspector, you can read the full
size of the sprite, which is sometimes
important to know. Now, repeat the process. Cell size is the same. This explosion effect will
be used later for animation. Here comes your first
mini challenge. You can go through other
sprites that need slicing. Slice, just the
sprites that have multiple objects
placed integrate. You don't need the
slice simple sprites. After you finish, See
you in the next lecture.
6. New Input System Setup: Hello everyone. In this video, we input a new input system and
adjust some settings. The first thing we
need to do is to go to Window Package Manager. By default, you should
see all packages that are already in
the project to show you all available
packages from Unity go to packages and select
Unity Registry. From the Unity Registry, we can search for
the input system, select it, and click
on the Install button. To finish the installation
process unity will restart. After death. If you go to packages
in the project, you can see that we have the new input
system on the list. Exit the package manager to make sure it's
correctly installed, we can go to Edit
Project Settings, select the player, and expand other settings.
Scroll down. We are looking for
active input handling. You can see the old system, the new system,
and both options. Make sure that the new
system or both are selected. I will select both. Nice. We have one more thing to do to simulate touch on the
screen with the mouse. We need to go to
Window Analysis. Input, debugger. Go to options, and enable, simulate touch
input from mouse or pen. Now, we can use the mouse
with the simulator, and that's it for the
basic preparations. See you in the next lecture.
7. Enhanced Touch Fundamentals: Hi everyone. Let's explore the
new input system. The new input system is super flexible and can be
used in many ways. From Unity, we can see
that touch support is divided into the
low level of support in the touchscreen class and a high level support in
the enhanced Touch class. The enhanced Touch class has
more options and control is designed for pulling in the update function and
unity recommends using it. So for this project, we will use the enhanced
stats class to control input. Once you know the syntax
and theory behind it, touch control
becomes really easy. First, we need to
enable enhanced touch. Usually we do it in their
own enabled function. Also, we need to disable it in their own disabled function
is pretty simple syntax. Then the enhanced touch provides access to information
along two-dimensions, by finger and by touch. So how we define a
finger and touch, each finger is defined as the nth contact
on a touchscreen. E.g. we touch the touch
screen with one finger, doesn't matter which one
that is the first contact. And some information is
stored in finger zero. If we touch the screen
with two fingers, information is stored
for both fingers. Fingers zero and
finger one variables. The fingers that are
touching the screen are stored in the
activity fingers array. So to get the information, we use the following syntax. Touch that active fingers. Since this is an array to get the information from
the first finger that is touching the screen, we use index zero to get
the second active finger. If it exists, we use
index one and so on. Okay, there is one
more array we use, and that is the fingers array. Notice there is no
keyword active. It is the array of
all possible fingers. They can touch the
screen at the same time. Usually this array has ten
elements for ten fingers, but it can be all over depending on hardware
and software. To use this array, we must check for an
additional condition. We need to check if the finger
from this array is active. If that is true, then we can use it. In the next example, I will demonstrate
the difference between these two arrays. This is really important. So take your time
to understand this. Let's say we touch the
screen with two fingers. This will represent the
active fingers array, and this will represent
the fingers array. Now we need to get some data, maybe their position
or something else. Let's say this is
the first finger that touched the screen. So it has index zero
for both arrays. That means this
finger has index one. Now, if we e.g. lifted a finger with index zero in the active
fingers array, the finger that had index one becomes the finger
with index zero. However, in the fingers, array, indexes stayed the same. But this finger is zero, is no longer active. When we lift all fingers from the screen, everything resets. To conclude, it's
important from which array and from which
index we get data. Now, let's take a
look at the touch. When you touch the screen
with a finger unit, they will store some information
in the touch structure. The structure is easiest to
explain using the phases. Every touch has began
and ended the phases. The beginning phase happens in the first frame when a
finger touches the screen. The ended phase happens when we leave the
finger of the screen. Between those two phases, we can also have them moved
and stationary phases. Of course, the phase is when we move our finger
on the touchscreen. And the stationary phase is when we don't
move our finger. There is one more phase
called cancelled. It happens when we
have a touch and we move away focus
from the application. Moving away or losing focus happens when we minimize
the application. These phases are very useful and we will use
them in the course. Also, there is an active touches
array that we can use to get active touches similar
to the fingers array. Okay, that was a little bit of theory about the
enhanced Touch class. Let's use it in the next lecture to create player movement.
8. Move Player with Touch: Hello everyone. In this lecture, we will
learn how to move the player using the new input system
and touch controls. To start, go to the
scripts folder, create a C-sharp script. I will call it player
controls. Open it. The first step is to add the input system enhanced
touched namespace. As we said in the
previous lecture, we need to enable
enhanced touched. We do it in their
own enable function. Remember, that
function is called whenever the object is enabled, then we disable it in their
own disabled function. That happens when the
object is disabled, destroyed and so on. Next, we need to receive
inputs in the update function. For this game, we
need just one finger. The best option is
to receive inputs just from the first finger
that touches the screen. It doesn't matter
which one physically, just that it is the first one. So in the if statement, we write Touch dot
fingers with index zero. Index zero meets
the first finger, you will notice one error. This is because this structure can be used for
multiple namespaces. So we need to specify
which namespace to use. We can right-click on the
touch and open quick actions. You can see that we
can use to namespaces, Unity engine that touch and Unity engine that
enhanced touch. We need to use enhanced touch. Now, at the top of the script, you should see that
every time we use touch, it is from the enhanced
touch namespace. Now, we can continue
with the if statement. We need to check if the
first finger is active, which means that it
touches the screen. Then we can use touch to get the first active touch from
the active touches array. We know that this active touch will come from the
first finger on the screen because of the if
statement from active touch, we need to get a position. First, we use vector three to store the screen
position of the touch. Since this is a screen position, we need to convert
it to our position. Screen position is a
position on the screen. It's different from
the world position. The world position is the actual position in
the scene and game. That is what we need.
For conversion. We use the main camera. The main camera has the
function screen to vote point. So we give it a screen position converted into a world position, and then store it again in
the touch position variable. We can also store
the main camera in a variable for
better performance. Let's create a new
camera variable. In the start, let's say the main camera two
camera dot domain. Now we can use the main
camera variable in the code. Then we can set the position of the player using the
new vector three. For x, we use touch
position that x and touch position y
for the y position, position on z axis
doesn't matter. It just needs to be in
front of the camera. I will set it to
zero. Let's try this. In Unity. Select the player and add the player
controller script. Press Play. I can click on the spaceship and move it across the screen. However, if I click
somewhere on the screen, the spaceship will
teleport to that position. This is not the
behavior we need. Idea is that the player doesn't need to click on the
spaceship to move it. The player should be able
to click anywhere on the screen and move the
spaceship from its position. In that way, the player has more visibility and
control over the screen. E.g. if I click here and
the spaceship is here, and I mowed the finger down, I want that spaceship also
goes down from its position. To implement that behavior, we need to calculate
the distance between the touch position
and the spaceship. Let's go back to the script. Create a vector three
offset that we will use is a distance from the
touch to the spaceship. As you know from the previous
lecture, touch has phases. If we just touched the
screen at that frame, touch phase is begin. So let's check if the phase of the first active touch is began. Notice there is an error. We also need to specify
namespace for detach phase. We use the input system
that touch pays namespace. Then to calculate offset values, a bit of vector math. Offset is equal to the touch position minus the
position of the spaceship, and that is transformed
that position. This will give us the
distance we need. Then we can check if the
phase is equal to move. That means if the player moves
the finger on the screen, of course, then we need
to move the spaceship. So we can use this code
with one modification. Subtract offset X from the x-coordinate and offset
y from the y coordinate. There is a phase
when the player is touching the screen and
is not moving the finger. So if the phase is stationary, then do the same thing. Set position with offset. And that is all we need
to code. Let's try it. First. Let's try clicking
on the spaceship. That works fine. Then click anywhere
on the screen and try to move the spaceship. You can see that the spaceship follows the touch correctly. This is what we wanted. Of course, there is a possibility
to go off the screen. In the next lecture, we will address that
situation. See you there.
9. Player Movement Restrictions: Hello again. Let's make some movement
restrictions for the player so he can't
go off the screen. Idea is to use a viewport. Let's take a look at
the mobile screen. The viewport space is normalized and relative
to the camera. What that means is that
values go 0-1, e.g. the coordinates or the
bottom-left corner are zero-zero. The first number is for the x value and the
second number is four, the y value, the coordinates
of the upper-right corner, R11, the bottom right coordinates are 10
and upper-left 01, the center point is 0.50, 0.5. We will use those coordinates and convert them
into virtual space. Then tell the player that he can't move past
those coordinates. Okay, now that we know the idea, Let's start open the
player controller script. First, we need private float
values for maximum left, right, down, and up points. In the start. We can
assign those values using the viewport to
world point function. So the maxilla left gets a
value from the main camera, that viewport to world point. As I said, we convert
view port to world point. Now we need to pace
viewport coordinates. So we use the new vector two. Since this is the maximum left
position for the x value, Let's try with 0.15. And for the y, we can use zero. You will see an error is
because this function returns vector three and we're
storing it in float value. But we only need an x
value from the vector. So at the end, right, that x for the maximum, right? The process is the same. Just change the x value
to make it symmetrical. One -0.15 is 0.85. For the mixdown value, the process is similar. Now the X coordinate
is zero and the y coordinate can be
a small number, e.g. 0.05. In the end, we choose the y
value with dot y. The max APP value will be 0.6 because I don't
want the player to move all the way to
the top of the screen. Okay, now that we know the restriction coordinates,
let's apply them. Go to the update function. I will just zoom
out a little bit because this will be
a long line of code. Now, inside the main IF
statement at the bottom override the position with the transform that position new vector three. To restrict values, we use the myth F, that clamp function. First we write the value
we want to restrict, and that is the x
position of the player. Then we write the minimum value, in this case, that is the
left side of the screen. So the max left position, then we write the maximum value that is the right
side of the screen, in this case max, right? For the y coordinates, we want to transform
that position dot y. The minimum value is max down and the maximum value is max up. For the z-axis, we
can just write zero. I think this is all
we need to code. Let's try it. You can see that now the player can't
get off the screen. Maybe we can increase the
bottom coordinates a bit. You can also see
that I can't move above 0.6 of the screen. Of course, you can
go to the script and increase the
max upper value. Now, I can move all the way up. Feel free to experiment with the values and find the
best for your game. This will work for any
screen size on any device. You can try it on other
devices in the simulator. Nice, That's all
for this lecture. See you in the next one.
10. Camera Boundaries: Hello everyone. In this lecture, we will adjust our camera for all types and sizes of screens. At this point, the
camera size is good, but on a different
mobile device, maybe it will be too
big or too small. To solve this problem, we use sinner machine
and a virtual camera. So let's import the
cinema machine package. Go to Package Manager and
select Unity Registry, find the center machine
and install it. Now, let's create
a virtual camera. You can reset the
transform component and set the z-axis
to a negative value. In that way, we make sure that the objects are in
front of the camera. Notice that now we control the camera size on
this virtual camera. Idea is to create
two empty objects on the side edges of
the screen and then make sure that those
two objects represent the edges of the kMer
regardless of the device. So they always need to be inside the camera view and act
alike edge boundaries. Let's create a new
empty game object. I will call it a left endpoint. We can give it an icon. Then reset the
transform component, move the object to the left. I think that minus
four is a good value. Don't go all the
way to the edge. Then duplicate the object. This will be right point the value for x and needs to be
symmetrical, so it's four. Now we need a new
empty game object. Call it target group,
reset the position. Then we can add the script from the city machine package at the scene machine
target group script. You can see that we can add
target objects to the list. We need to targets. One is left point and
another is a right point. Great. Now select Virtual k-mer. Drag the target group into
the fall and look at fields. Since we are using a group
of objects for the aim, select group composer, we need to change a
couple of options. The first one is
group framing size. It defines how much
screen space is taken up by the bounding
box of the targets. We need to set it to one
so that the edges of the screen are exactly on
left and right points. Then set the frame
damping to zero. The lower value, the
fester camera will adjust itself to the correct
size when the level starts. Now, you can try it
in the simulator, change the devices, and
see how the game looks. It should be fine. However, there is
one hidden problem. Notice that a
movement restrictions are not working
correctly anymore. The reason is that we set restrictions in the
start function, but the cinema
didn't have time to set the camera correctly
at the start of the level. So the view port from
which we get coordinates, sense of wrong data. The solution is quite simple. We can use Coroutine
with keratin function. We can delay the
execution of code. The syntax is a
little bit different. We need to create the
numerator function. In the function, the code is kinda separated into two parts. In the first part, we do something or nothing
depending on what we need. In this case nothing. Then we add time delay. We write yield, return new, and then choose how
long the delay will be. E.g. we can wait
for end of a frame. We can wait for a certain
amount seconds, and so on. Let's wait for 0.2 s.
After time passes, we execute the second
part of the code. In this case, we need it
to get restriction values. Those 0.2 s is enough time
before seen a machine to adjust the camera and then we get the correct view port data. Actually, let's use a
weight for end of a frame. For this example, we expect that one frame is enough time
to adjust the camera. The last thing we need to call this function with
start coroutine. Use start coroutine in the start and call the
set boundaries function. Let's try it. Now.
Everything works fine. Note that sometimes
seen a machine needs more time to
adjust the camera, e.g. on all their mobile devices. So maybe it's smarter to have
more time delay. That's it. I hope you understood everything and see you
in the next lecture.
11. Touch Controls Update [Don't skip]: Hello everyone. This
is a quick update. It seems that unit is
new input system and some Samsung devices have
compatibility issues. Don't worry, I will show
you how to fix them. Maybe even by the
time you watch this, unity and Samsung already
solved this issue. In that case, you don't
need to make any changes. Let's see the problem. For some reason, Samsung devices don't
register this line of code. I think that they
have problems with the fingers array or
something like that. But actually they register it, but only when using
a stylus pen. They will not registered
the naked finger, which is really strange. Other Android devices and iPhones don't have that problem. So let's replace
that line of code. We can use the touch class
to count active touches. So, right, touch that
active touches that count. The count needs to be
greater than zero. That means we have one or more active touches
on the screen. Let's try it. Here I have a Samsung device
and everything works. However, the player can abuse movement behavior by
using multi-touch. Notice that if I use
more fingers and I lived the first finger
that moves the spaceship, the spaceship will teleport to the position of
the second finger. To prevent that, we need
another if statement. Let's use the first
active touch. It has index zero. Then let's use the finger
and index around that touch. The index of that finger
must be equal to zero. That means we use only the first finger
that touches the screen. Then move the code
inside the if statement. Let's try it. As you can see, now,
everything works. I would suggest that you use this approach since it
works on all devices. I hope unity and Samsung
will fix their issues. In the meantime,
make sure you test your code on as many
phones as possible. But we are not done. Another bug can appear
in Unity editor. The bug I'm about to show you only happens in Unity editor. It will not affect your
published game on mobile phones, but it can be annoying when
you test your game in Unity. Of course, I have the solution. First, let me show you the bug. I can control the ship normally while my mouse is on the screen. But if I click outside
of the screen, I will get this error. The same happens when you hold the left mouse button and drag the mouse outside of the screen. Basically, it happens
every time you press outside of
the mobile screen. When you build your
game on the phone, you can't press
outside of the screen. The screen is the only
thing you can use. So I don't know why Unity editor register screen positions
outside of the screen, but I know how to fix it so that this error
doesn't annoy you. You can notice that the values
for the screen position r infinity for x and negative
infinity for the y-axis. We can use that information. Go to the player
controller script here below vector
three touch position. Let's write hash,
if Unity Editor, and then write hash. And if now everything
we have right between those lines will be compiled only in
the Unity editor. It will not be compiled when you build your game to phones. Here, we can check if the touch position on x
is equal to infinity. If that is true, then return and don't
execute the code below. So in the Unity editor, when we press outside
of the screen, the code will stop here and
that will prevent errors. Let's try it. I will drag the mouse outside of the screen and nothing happens. I can click anywhere and
I don't have errors. Nice. I hope unity will solve these
errors in newer versions, and that is all for this video. See you in the next one.
12. Tap Count: Hello everyone. In this lecture, we will learn how
to count steps. This lecture is optional. We will not use steps in
this space shorter project, but maybe it will be useful
for your games and projects. You will expand your knowledge
about touch controls. If you open documentation, the link is in the resources. Then under the Touch class, you can see all properties
that we can use. Some of them we have
already seen and used e.g. phases and screen position to count how many
types the player did, we need the tape count property. Let's open the player
controller script. E.g. let's say that we need
to register a double-tap. We need one if statement. Then we use the touch class, in our case, my
touch a variable. So my touch, that type count. If the count is two, then we can do something. And that's it. It's that simple. Let's try it. I will simulate a double-tap
with a double-click. You can see the console
that we have debug log. Nice. Of course, you can change
the number of tapes, e.g. we can check for one tape. This is all for this lecture. Hope you learned more about touch controls and see
you in the next one.
13. Virtual Joystick: Hello everyone. In this lecture, we will add a virtual joystick that we can
use to move the spaceship. As you can see, I can move the spaceship by moving
this virtual joystick. Note that this is optional. We will not use this
approach during the course. I will use touch controls
for the rest of the course. You can still follow the course with this
joystick option. But the main reason for
this lecture is to show you how easy it is to
implement a virtual joystick. Maybe you will use it in your
future games and projects. Okay, Let's start. As I said, we will use
a new input system. I will repeat the import process in case you skipped that part. First, we need to go
to Package Manager. Makes sure you select
Unity Registry, then search for
the input system, select it and click on
the Install button. I have already done that. Then right-click on
the project window to create input action. I will call it controls. Click on the Edit button. This will open a new tab. Click on the Plus button to
create a new action map. This action map will
be for the player, so call it player. Then we have actions. Actions can be e.g. shooting, movement, and so on. Every action has one
or more bindings. Bindings are like triggers. We determined what button to press to activate the action. I will just delete this action
to show you the process. To create a new action, click on this plus button. This action will
be for movement, so call it moves. You can see action
properties here. We need to change
the action type. For the joystick. We don't need a button, we need to use a value. Also. We need to set the
control type to any value or use a vector to. Then select the
binding and open, open and gamepad and
select a life at stake. Now, when we are done, It's important to
save the asset. If you make some changes, remember to save it. Then select the player. We need to add a player
input component. Then dragging the asset
controls that we made. Now let's create the
UI for the joystick. We need one image. I call it a left stick. Go to the scene view. Select the image. I will just zoom
in a little bit. If you want to have a joystick
in the bottom-left corner, then we need to change Anchor, Preset and pivot point to
the bottom left corner, hold Shift and Alt and choose
the bottom left corner. We can change the
position a bit. Then let's add the own
screen stick component. For the control pet. Choose the same pace as
we did in our controls, and that is the left stick. Let's test this. You can see that the
image is behaving like a joystick, but
nothing happens. Player is not moving. Before we deal with that, Let's adjust the joystick a bit, move it more to the corner. Then let's change the image. Check the link in the resources for more free virtual
joystick images. We can also increase
the scale a bit. This looks better. Notice there is the
movement arrange variable. It determines how far the joystick we will move
from its center. Let's increase it to 100. This is much better. Also to make UI compatible
and scalable for all devices, we need to select Canvas. Then change the scale mode
to scale with screen size. Then set a reference resolution. Let's match width
and height equally. So set this to 0.5. All we have to do now is to connect the joystick
with player movement. Let's select the player. I have the player
controller script. Let's open it. To make the joystick work. First, we need to create
one input action reference. Back in Unity. Expand the controls set. You can see action, move, drag it in the empty field. Go back to the script. We will need one
float variable speed. Then in update, Let's use
vector for the direction. We will get the direction values from input action reference. So use move action to use
that action that read value. Sticks on gamepads have
vector two values. That means that we
read value vector two. To actually move the player, use transform that translate. We multiply the move
direction vector with the speed variable and then multiply
everything with time, delta time for smooth movement. That is all we need to
coat back in Unity. Don't forget to set the speed. Let's try it. Now you can see as I move the
joystick, the player moves. Nice. That is all for this tutorial and see you in the next one.
14. Enemy Concept: Hi everyone. In this lecture, we'll learn how
to create enemies using the inheritance concept. The best practice to use inheritance is when
you have a group of objects that have a lot of common functionalities, e.g. a, group of enemies. The concept is very simple. We create a parent also
known as a base class. Then we create child classes. Child classes will inherit variables and functions
from the parent class. In addition, child places can have their own variables
and functions. Let me show you an example. First, to stay organized, select the scripts folder and create a new one
for enemy scripts. Then let's create the
new C-sharp script. Call it NME. It will
be our base class. Open it. Okay. All enemies needed to have health that is common
for all of them. So create a public
float health variable. Now, we can create
a child class, e.g. Meteor. Open it to make
this a child class, replace motor behavior
with the enemy class. For now, leave the
child place like this, no variables or functions
other than start and update. In Unity, we can create a new empty game object,
the meteor script. And we can see the
health variable. The health variable
is inherited from the enemy class and we can
use it in the Meteor class. Let's go to the enemy class. Usually we can use protected variables
instead of public ones. Protected variables
are something in between private and public. They are visible just the
parent and child classes. Other places can see or
change them directly. That also means we can't see them in the inspector
by default. For that, we use
serialized field. Nice. Let's take a look
structure a bit more. We have a parent class, enemy child meteor
class, and we can e.g. create a spaceship child class. So both meteor and spaceship
need to have health. They need to have a rigid body, probably in animator for
animations and so on. All that stuff that is common
goes in the parent class. Also all enemies
can take damage. So we can create the take damage function
in the parent class. Child classes will inherit
those variables and functions. As I said, in addition, we can have specific functions
just for child classes. The meteor class can have e.g. rotate function and spaceship
can have a should function. And that is the basic
logic of inheritance. Now, let's go to
the enemy script and create the take
damage function. Makes sure that
is public because other classes we'll
call this function. Also. It needs to take one
float damaged parameter. In this function, we will decrease health with
the damage value. Then we can add some
damage animation. After debt, we can check if the health is less
or equal to zero. Then we can maybe play
a destroy animation. Later, we will write
actual code for debt. Now, I will show
you one advanced the trick with
virtual functions. Virtual functions work really well with inheritance pattern. So we create a virtual
function in a parent class. All child classes can use
that virtual function, but can also override it. That means adding some
code and functionality. Let's say the syntax. We create a public
virtual void function. Notice the keyword virtual. Let's call it hurt sequence. And we can also
create that sequence. Now, replace comments
with functions. When the enemy takes the image, the herd sequence happens. That sequence happens when the health is less
or equal to zero. We can add some functionality to virtual functions if we need. In this case, we don't need it. Let's go to the meteor script. Since this class
is a child class, we can override
virtual functions. Notice the keyword override. By default, code from the
base class will be called. So if you have something here in the virtual function
that will be called, but remember that we don't have to call it, it's an option. So we can just delete
that line of code. We can do something different and unique for this child class. In that way, every
child class can have different hurt and that
sequences and behavior, e.g. one enemy type can
explode in that sequence. Another enemy type can e.g. explode and also
spawn more enemies. The possibilities are endless. Okay, that is all theory we need to know.
Through the course. We will add more stuff
to the base class enemy. In the next lecture, we will apply this knowledge
and make the first enemy. So see you there.
15. Meteor Prefab: Hi everyone. In this lecture, we will create material prefers that can destroy the player. First, we can delete the meter objects from
the previous lecture. Then we can go to enemy sprites and drag 1 m into the scene. We can rename it to make sure that enemies are visible in front
of the background, increase order in a layer. Notice that the
player is too big. It would be too hard to avoid
meteor same projectiles. We can change the
scale maybe to 0.6. Great. Now select immature to put
this object under influence of the physics engine and forces at the rigid body 2D component. We will meet you're using
this component in the script. Notice there are some
settings like gravity. If we press Play, the object will fall. To actually collide
with other objects, we need a collider, in this case,
circle collider 2D. Let's zoom in to see better. I will decrease the
radius a bit perfect. We also need to add a Rigid Body and collider
components to the player. Ed, rigid body 2D. For the player, we can
set the gravity to zero. The player has more
complex sprite. So we can add
polygon collider 2D. To increase performance,
we can remove some lines from the collider on the
edit collider button. Now, hold control and click on the line when becomes
a right to remove it. We can also move some vertices. I will speed up a bit. You can edit the
collider as you wish. It doesn't need to
be the same as mine. We can exit edit mode. Now select the meteor. To avoid selecting
the background, we can disable selection, move the meter to the middle. Now, we can taste collision
in the play mode. As you can see, objects collide. The next step is to enable the East Trigger option
on the meteor collider. Now, the objects
will not collide, but collision is detected and we can use it in the script. Next, change their rigid
body type two kinematic. Now, other objects and forces
can't affect this object, which means nothing can
push or pull this meteor. We can control movement
only through the script. Also, remember any
object that has a collider and you intend to
move, destroy, or change. It needs to have a
RigidBody2D component. We can add the meteor
script and move it up in the inspector. Open it. Before we start coding here, Let's go to the
parent enemy class. All enemies will have a
rigid body 2D component. So we can create a
protected variable, RB. In Unity, you can drag the rigid body component
into the empty field. Now go back to the
meteor script. I want to create materials with different end random speeds. So create to float variables that we can
see in the Inspector. One is minimum speed and
other is maximum speed. And we also need one private Cloud speed
in the start function, we can set the speed. Speed will get the value
with random that range. So the value will go from
minimum speed to maximum speed, which we set in the inspector. Now, we need to add
velocity to the mature. So we use rigid body RB, that velocity and set
it to vector to down, which means a negative value. On the y-axis, it's minus one. The meter will move down and we just need to multiply
direction with speed. In Unity, set minimum
and maximum values. Let's test it. Nice. Now, let's detect a collision between the meteor
and the spaceship. We use the On Trigger
Enter to d function. This function will be
called when something enters the trigger that
we have on the Meteor. You can see that
the function has one collider 2D parameter. Let's rename it to
other collider. Later, we will have a damaged system and we
would damage the player. But for now, let's just
destroy the player. We use the function
destroy and we want to destroy other
collider, that game object. So this is the object
immature collided with. Let's see it. Nice. However, the meteor can
touch other objects. So we want to specify just
to destroy the player. There are many
ways how to do it. We will use tags, select the player, and
go to the drop-down. Select the tag player. Of course, you can
create a new tag here. Just click on the plus button. I will not do it now. Just make sure that
the tech player or whatever you use is selected. First, we want to check
if the object has the player with the
compare function. If that is true, then destroyed. Great. Now we need to
create a prefab from detonator is like a copy of the object with
all its components. First, let's create a
new folder, prefabs. Then drag and drop the meter
objects from the hierarchy. Now, we can easily create copies of that
object in the scene. We will use this prefab for
the spanner in the future. If you go to the enemy sprites, you will see two more meteors. Your mini challenge is to create prefabs from these sprites. The solution is very simple. You can repeat the process to remember everything
we have done, but there is an
easy way to do it. We can select the prefab
from the hierarchy, replace the sprite, rename it, and drag the prefab into
the Prefabs folder. We want to create a
new original prefab. Then do the same to
create a third Prefab. And that is all
for this lecture. See you at the next one.
16. Collision Matrix: Hello everyone. Before we make a spammer four
meter prefabs, I will show you one useful trick about collisions
between objects. We will explore the
collision matrix using the collision metrics, we decide between which layers the collision will be detected. So first, we need to
create more layers. Select the player and go to the upper right corner
in the inspector. Remember here our
layers for collisions. We already have some
default layers, but let's create new ones. Go to add layers. Let's create the layer player. We can also create
one for enemies. Now select the player and
assign the layer that we made. Next, we can select the meteor
prefab from the hierarchy. The material should be
on the Enemy layer. For prefabs, it's important
to override changes if you want to apply them to the other instances
of the same prefab. Now, if you go to the Prefabs folder,
select meteor three, and you can see that
he is already on the Enemy layer because of
the override we applied. Now select the other 2 m and
change the layer two enemy. Since we made the changes
directly to the assets, we don't need to
override anything. You do overrides just when making changes to prefabs
in the hierarchy. Now, go to Edit Project
Settings and select Physics 2D. Go to layer collision matrix. Here you can see all
the collision layers and relationships between them. By default, a collision
between all layers is enabled. You can also see the layers we made to disable collision
between the layers, just uncheck the box. In this case, we disabled the collision between
the default and NME layers so we can
continue disabling collision until we get
to the layer player. We need a collision between
the player and enemies. So leave that checked. Next. We don't need
collision between enemies. For the layer player also
disabled other collisions. Just to show you, if you're disabled collisions between the enemy
and the player, the meteor we'll go
through the player and collision will
not be detected. So make sure
collision is enabled. This is a nice way
to control what will collide and
what won't collide. You should definitely use
this in your projects. Later in the course, we will add more layers
and modify this matrix. That's all for this lecture. See you in the next one.
17. Meteor Spawner: Hi everyone. In this lecture, we will
create a spammer for meteors. We also make sure that
meteors found outside of the screen and inside the left
and right edge boundaries. First, let's create a
new empty GameObject. This there'll be
meteors partner. We can reset the
transform component. Then we need to create
a new C-sharp script. Call it matures pounder, the script to the game
object and open it. Now, let's create
some variables. We need an array
of game objects. This array will hold
the meteor prefabs. Then we need the
spawn time variable. This variable will determine
when meteors will expound. We need a timer to
keep tracking time. And the integer variable I
is an index for the array. Next, we need a reference
to the main camera. Of course, we need
a maxilla left and max right variables
for screen edges. And in this case, we also need a y position
variable that will be outside of the screen to make sure meter span at
the right position. In the start function, Let's set up a reference
for the main camera is the same way as we did in the player controller script. We can also go to the
player controller script. Here we can copy the set
boundaries function. Let's paste it into
the spawner script. We can delete the marks down
and max upper variables. We use a maxilla left
and max right variables. Feel free to tweak these
numbers if needed. We need to add one variable, and that is why position. That position needs to be
outside of the screen. So for the y value, use something greater than one. I will use 1.1. Next, call this function in the start with start coroutine. Now, let's create the main
logic of the spawner, calculated time and meteors. By default, the timer is zero, but we can make sure
and set it to zero. Then we increase the
timer by Time.deltaTime. Time.deltatime is the
time between two frames, is we update frames, the time will increase. Then we check if that timer
is greater than our time. If that is true, we need to spend one of
the three meter prefabs. We set the index I to
random that range, which goes from zero
to meter that length. In this case, the index
will be number 01 or two. Now, when we have
an index number, we can spawn a meter prefab from the array to create objects. At runtime, we use the
Instantiate function. First, we write the
object we need to spawn. In this case, that is a meteor prefab from
the array with index i. Then we choose this
bounding position. We need a new vector three. For the x value, we use random that range. It goes from maxilla
left to max, right. This will expound meteors
within screen edges. For the y value,
we use y position. Remember, the value is above
the top of the screen. For the z axis, if you use any
number that will put the object in front
of the camera. I think that our
camera is minus ten, so we can go minus five, e.g. next, we need to
set the rotation of the object to choose
the default rotation, we can just use
quaternion, that identity. But to make it look better, Let's use random rotation. Set the rotation using
quaternions that Euler, x and y values need to be zero. And for rotation on z-axis, we use a random
that range 0-360. Then we need to reset
the timer to zero. Great. Let's go to unity. We can choose spawn time, e.g. I. Will set it to every 2 s. Then we can add Meteor
prefabs to the array. Loved the inspector and
go to the Prefabs folder, select meteors, and
drag them to the array. Make sure that you use
prefabs from the assets. Don't use prefabs
from the hierarchy. Let's try it. Nice, everything works. However, we need to take
care of one problem. I will increase the spawn time and play the game a little bit. You can see in the hierarchy that we have a lot of objects. Those are meters that we avoided in their
fall into infinity. To solve this, let's
go to Demeter script. We will use the function
on became invisible. This function will
be called when the object is no longer
visible to the camera. In other words, when the
object leaves the screen, then we just need to call the destroy function and
destroyed this game object. Let's test it. Now, you can see
that meteors are destroyed as they
go off the screen. Nice. To make this boundary
even better, we can randomize the size
of the meteors, respond. In the spawner script, let's store the object was found in the game
object variable. Then we can create a random variable for
the size of meteors. I will set a really small range. You can increase the
difference if you want. Then we change the local
scale of the meteor. For x and y, use the variable size. Great, this is all we
need to code here. See you in the next lecture.
18. Object Rotation: Hello everyone. Before we add shooting
ability to the player, I decided to squeeze in this lecture about
Meteor rotation. This is optional,
but I think that the media Roseville look
better if they rotate. The goal is to
rotate meteors on z, x is in the script. Let's delete this prefab from the hierarchy open
Demeter script. First, we need float
variable, Rotate, speed. Then in the update function, we need to rotate the
object every frame. We use the Transform
Rotate function. For x and y axis. We don't need the rotation. And for Z-axis, use Rotate speed and multiply
it with time, delta time. We use the Time.deltaTime so that the rotation
looks nice and smooth. This is all we need
to code in Unity. Select a meteor prefabs
and set a rotation speed. Let's try it. Nice. I think that this
looks much better. That's all for this lecture. See you in the next one.
19. Player Shooting: Hi, again. Let's add shooting
ability to the player. In this lecture, we will create basic shooting from
one shooting point. Upgrades and shooting for more points are done
later in the course. First, we need a position
from which we will shoot. So right-click on the player and create an empty game object. This object is a child
object of the player. I will call it basic
shooting point. We need to move to shoot in position a little bit
about the spaceship. Then create a new
C-sharp script. I will call it player shooting. Open it. As always. First, let's create the
variables that we need. We need one game object variable for the laser bullet prefab. We need a transform point
from which we shoot. Then we need the shooting
interval variable. Also, let's create one float variable so that we can
reset the interval. This shooting interval value
in unity in the Inspector. And then in the start function, we can store that value in
the interval reset variable. Next, there are many ways
how to create timers. We already made one
for this pounder, but for this case, let's create a timer by
decreasing the value. Every frame, we decrease shooting interval
by Time.deltaTime. If that shooting interval
is less or equal to zero, then we can show
21 laser bullet. Before we create a
function for shorting, let's just reset the interval by setting it to the default value. Next, create a function to span objects we use
instantiate is you remember, first we write the
prefab we need to pound and it is a laser bullet. We need to spend it on the
basic should point position. We can use default rotation and use quaternion
dot e. The entity. Then call the function when the interval is less
or equal to zero. In Unity, select the
player and add the script. You can see that
we need to set up some references. For now. We don't have a
laser boy at prefab, but we have a shooting point. Drag the point that we made
at the start of the lecture. We can also set the
shooting interval to 0.3 s. Now, let's create a
laser bullet prefab. Go to sprites player. And here you can see
the projectile sprite. Let's drag it into the scene. Rename it. It's a bit too big. So set the scale to 0.5. Then add the rigid
body 2D component. Choose the kinematic body type. Next, we need a collider. I will use capsule collider 2D. Let's adjust the collider a bit. It needs to be smaller. Then enable the Is
Trigger option. Now, let's create a new
collision layer for projectiles. Go to Add Layer. I will call it
player projectile's. Select the object and choose the player
projectile's layer. Remember, when we
create a new layer, we need to modify
the collision matrix for better collision control. I want that the projectile is
collide just with enemies, so disabled other collisions. Finally, we can create a
script for the laser bullet. The script to the object. Open it. Let's create variables. First, we need the
speed of the bullet. Then we need the
damage variable. This variable will determine how much damage the
bullet will do. We also need the rigid
body 2D variable. In the start function, we set the velocity to transform that up multiplied by the speed. Transform that up is
the direction and it is represented by the
green axis in the scene. This will make the
bullet move up. We don't need the
update function to detect collision with the bullet we use on Trigger Enter to D, then we don't need to check what collided with the bullet because
of the collision matrix. We know that just enemies
collide with the bullet. So from the collision, we get the enemy component. Remember that enemy class is a parent class to all
types of enemies. So every enemy type as the enemy script
is a parent class. The enemy script, we have the tech damaged function that take damage function
will damage the enemy. Now, when we got the component, we can call the function
enemy that take the image. The function takes
one argument and that is the damage we
will do to the enemy. Then destroy the bullet. However, there are cases when
bullets will miss enemies, then we need to
destroy those bullets. Same as meteors, videos
that aren't became invisible function
when the bullet is of the screen destroyed. Now go to Unity, connect the rigid
body component. Set speed and damage. I will set the image to one. Now, drag the bullet
to the Prefabs folder. Delete this one from
the higher here. Select the player and drag the bullet prefab
from the assets. Let's try it. As you can see,
collision is detected, but we don't destroy meteors. A simple explanation for that. Select one of the major prefabs. You can see that health is 0.1 bullet should be
enough to destroy it. Let's go to the meter or script. We are searching for the
deaths sequence function. Remember this function
is called in the tank damaged function when the
health is zero or less. And we call the thick
damage function when an enemy collides
with a bullet. So everything is
connected correctly, but that sequence
is doing nothing. It is empty. We just need to destroy the
meteor in the death sequence. In Unity, select
all Meteor prefabs. If you want the meteor destroyed with one bullet
set Health to one, I will choose two, which means two bullets to
destroy it. Let's try it. Nice, everything works. See you in the next lecture.
20. PlayerStats and Damage System: Hello everyone. Let's create a health and
damage system for the player. Through the course, we will operate the system
with animations, game manager, logic,
and other stuff. But the core functionality
is done in this lecture. First, we need a
new C-sharp script. I will call it the prior states. The script to the player. Open it. Let's create
some variables. We need a float, mocks
health variable. This will be the maximum
health for the player, which we determined
in the Inspector. Then we need one
private variable, health that will represent
the current health of the player in
the start function, Let's set current
health, maximum health. We don't need the
update function. Now, let's create a function so that the player can
take the image. I will call it
player take damage and it takes one
parameter, damage. As you can see,
the damage system is similar to the
enemy damage system. Here, we decrease that
health by damage amount. Then check if health is
less or equal to zero. If that is true, then we can destroy the player. In the future. There will be a lot
more logic here, animations spanning explosions, showing the death
scene and so on. Now go to Unity. I will set maximum health 23. Go to the enemy script. All enemies will deal damage. So it makes sense to create a damaged variable
in the parent class. In Unity, select
a meteor prefabs, and notice there is a damage
variable in the Inspector. I will set the damage to one. Then open the material script. If you remember, when a meteor
collides with the player, we immediately
destroy the player. We can comment
that line of code. Idea is to damage the player. Now, we can get the
player stats component. From the player stats we call the player take the
image function. The function takes
the damage variable that we created in
the enemy clays. Let's also destroy the meteor. Now, we can try it. The player should be destroyed
after three meter hits, since health is three and
damage is 112.3, it's working. Of course, it would be nice to see how much health
to the player has. So in the next lectures, we will create a health
bar for the player.
21. UI Fundamentals: Hello everyone. In this lecture, we'll learn
about UI fundamentals. Have the proper is
set up a Canvas, how to properly position
you are elements in more for creating a
helper and main menus, it's necessary to know
fundamental stuff. First, let's right-click
on the higher here. And here you can see
all UI elements. The most common, our
image, text and button. Let's create an image. This will automatically create canvas image and events system. Before we start working
with the image, let's select event system. Because we are using
a new input system, we need to replace this module. This will enable
interaction with buttons and other interactable
elements in the future. Now, double-click on the
canvas to see the full size. By default, the Canvas
has the same size screen. Let's select our image. Change position to zero-zero. Now, the image is in the
middle of the screen. If you go to simulator, you should see the image. The first thing we need
to change is to make UI elements scaled
depending on the device. That means on smaller devices, UI elements need to be smaller and bigger and
bigger devices, e.g. I. Will change to
a bigger device. Notice that the size of
the image is the same. This is not what we need to change the size, select Canvas. You should see the
canvas scalar component. Then change the scale to
scale with screen size. Notice that the image is bigger. The next step is to choose
a reference resolution. Since this game is for
portraits perspective, let's set the resolution
to a nine to 16 ratio. And we want equal image
width and height. So set the image to 0.5. Now, when you change devices, the size should
change correctly. Maybe it's hard to
see on this square, but the way the real sprites, the change, it would
be more visible. Now, let's move on to the most common mistake
I see people make. Let's say we need to create a health bar width, this image. The Health Bar needs to
be in the upper corner. Let's select the image and move it to the
upper left corner. You can see that
in the simulator, the position is good. However, let's choose
a smaller device. Now you can see that the
image is of the screen. Why is this happening? The answer is anchor position. Select the image and
open the Anchor Presets. By default, the anchor position is in the middle of the screen. You can see the anchor
position on the Canvas. How do anchors work? Actually, they are
really simple. The distance between
the anchor position and the object is
always the same. So this distance will be
applied for every device. On smaller devices, that
distance is too big, so the image is of the screen. Another example,
Let's say this is our test device
and the distance. If we choose a bigger device, the image would not
be in the corner. It will be closer to the
middle, then it should be. The solution is to choose
another anchor position. In our case, the anchor needs to be in the
upper left corner. Now, we use this distance from the upper left
anchor to the image. This will work for every device. Now, let's choose the
upper-left Anchor Preset. We can also hold the shift to set the pivot point
to that corner. Now, change devices
in the simulator and see that the image is
in the correct position. Okay, we now have to correctly place UI elements
for all devices, which means we are ready
to create a Health Bar. See you in the next lecture.
22. Health Bar: In this lecture, we will create
a helper for the player. To start from zero. Let's delete the image
from the previous lecture. Now let's create a new image. I will call it Health Bar shape. We have a sprite for this image and drag it into
the source image field. If we zoom in, we can see that the shape
is looking deformed. So click on the Set
native size button. Now the image has identical
dimensions as the sprite. However, if we tried to
change the height and width, the shape will deform. To fix it, select the
Sprite Sprite Editor. We will use the nine
slides technique. It's called nine
slides because we divide the sprite
into nine pieces. Look for the green square, then you can pull
the green line down, make sure that it is
below the corners. The goal is to separate
corners from sides. For this line, makes sure
that it is above the corners. Then we have a left
and right aligns. You can see that the sprite
is divided into nine pieces. The corners will not stretch in the form only the
sides will stretch. Apply changes. Then select the image and
change the type to slice. You can see the difference
when we change dimensions, the shape doesn't deform. Nice. Let's right-click on the canvas and create a new
empty game object. I will call it bar. Bar will be a parent object
to health bar shape. Let's select the shape. Go to Anchor Presets
and stretch it. Hold Alt and click on
the stretch button. When we change the dimensions
of the Health Bar, which is a parent object, the shape will adjust. Let's create a new
child image object. I will call it
health background. I will use the square of Sprite. Let's change the color. Then go to Anchor
Presets and stretch it. Move it up one place in the hierarchy so that
shape is visible in front. When we zoom in a lethal
because we have round edges, the background image is
visible outside of the edges. If you choose another color, it would be more visible. To fix it, Let's just
change the dimensions. Then. We can create a child
image of the background. I will call it health field. We can also use the square
sprite and stretch it. Now, change the color. I will choose yellow, then change the image
and select field. We can see some settings. The idea is to change this fill amount as
we change health. First, let's change
the fill method from radio to horizontal. This will give us the
desired behavior. Notice that fill
amount has values 0-1. Let's zoom out, select the helper and change the anchors to the
upper left corner. Hold out to also
set the position. Adjust the position a bit. Maybe we can change the color of the shape to make the edges thicker. Let's increase the size a bit. Now, this looks good. Let's see how it looks
in the simulator. Great. Let's go to the
player stats script. First to get access
to UI elements, we need to include
the UI namespace. Then we can create
one image variable. I will call it help fill. Idea is to change the fill amount every time
the player takes damage. Also, it's a good idea to set the fill amount when
the game starts. So in the start function, we've helped fill that fill
amount equals to health. But as I said, the value must be 0-1. So we divide the health
by maximum health. We can copy and paste that
code into the player, take the image function, and that is everything
we need to code. In Unity. Drag the health
field image to the image slot. Let's try it. As you can see, we have full health. Let's take damage. Nice. The Health Bar reacts. I will add more elements to the health bar just to
make it look better. It's not essential. So I will create a child
image of the shape. Use the icon based
sprite and change color. The anchor needs to be
middle left called out to also set the position and
resize that image a bit. It goes to the left. I will call this icon hold her. Then create a child
image of the holder. Use the Help icon
sprite and resize it. Anchor Presets are
relative to the parent. So this needs to
be in the middle, just as it is. Now. We can select the Health Bar and place it in the
right position. Fine. Maybe the edges
should be a bit thicker. We can increase the size a bit. You can play with the
settings as you like, every game is different. That's all. And see you in the next lecture.
23. Safe Area Helper: Hi everyone. In this lecture, we explore one free
asset that will help us adjust your elements
for all devices, e.g. every device has a safe area in which elements are
guaranteed to show properly. You can click on the
safe area button to see the safe area
for this device. Every device has a
different designs and different safe zone. Let's change the device. E.g. it shows April XR. Notice that because of
different designs are held bar is not fully visible. So idea is to place
the heel bar and other UI elements inside the
safe area for every device. Luckily, there is one called asset in the Unity Asset Store. You can Google Safe area helper. It should be the first option. This is what it looks
like. It is free. So click on Add to my assets. Of course, you need to
sign in to your Unity ID. If you didn't. After that, click on Open in Unity or whatever is an option. In unity, the package
manager should open. You can see that package
manager has the option, my assets on the list should
be the safe area helper. Then you need to download it. I already did. So I have a download button. After you download the assets, click on the Import button. We don't need the demo scene. If you want to see that example, feel free to include it, but we only need this safe
area script. In the project. You should see the script. Now right-click on the canvas and create an empty game object. Let's call it a safe area. Then we need to stretch
it across the screen. The safe area object
needs to be a parent to the Health Bar and other UI elements that
we need to control. Then add the safe area script. Make sure that conform
x and y are enabled. Now, if we press Play, the Health Bar will
be in the safe area. We can test it on other devices. Great, it works perfectly. So e.g. if we have the **** bar in the
upper right corner, without this asset, it will
not be visible at all. But with the asset It
looks just as it should. That's all for this lecture. See you in the next one.
24. Explosion Animation: In this lecture, we'll learn how to create animations, e.g. when objects are destroyed, we use explosion animation.
To stay organized. Let's create a new
folder for animations. First, we need to find the
sprites that we will use. In the enemies folder. We can see explosion Sprites. Let's use the first
one in the scene, rename it to explosion. We can't see it in the scene because of the
order in the layer, we need to increase it. I want this explosion to be visible in front of everything. I think that the
player has ordered ten and a transparent
background is 12. It's a good thing to
write down that things. So we need to go
higher than that. Let's set it to 20. In bigger and more
complex games, I recommend creating and
using more sorting layers. Now, let's open some
animation tabs. Go to Window Animation and
open the animation tab. Let's also open
the animator tab. We use the animator tab for animation transitions
in the next lecture. Then make sure you select the
object you want to animate. To create animation, click
on the Create button. Select the Animations
folder that we created. I will call this animation
explosion example. If you take a look
at the object, now we have the
animator component, which has a controller. Those are necessary
components for animations. Go to the Animations folder. Here you can see
the controller and the animation
example we created. Next, select the
explosion object and drag all explosion Sprites
into the timeline. Let's see how it looks. Animation, but it's still fast. We need to slow it down. Select the explosion,
expand options, and choose Show sample rate. Now you can set the frames per
second for this animation. By default, it's 60, Let's set it to 12. It looks much better. However, you can see
that animation repeats. We need to go to the
Animations folder and select our explosion
example animation. We need to disable loop time. Nice. It's a good idea to destroy the object after the
animation is finished. So let's create a new C sharps. I will call it explosion. The script to the
object. Open it. We don't need the
update function. In the start. Let's destroy the object with a delay of 2 s. Let's test it. The animation runs one
time and after 2 s, the object is destroyed and we can see it in the hierarchy. Now, we can create a prefab. Delete the object
from the scene. Idea is to spawn
this prefab when meteors or the player
are destroyed. Since all enemies value is this explosion prefab go
to the enemy script. Let's create one game
object variable. Now, go to the meter of script. In that sequence before
we destroyed the meteor, let's bound the
explosion prefab. We can use the position and
rotation of the middle ear. Let's also spawn it. When the meter collides
with the player. Then go to the
player stats script. We need this boundary explosion prefab when the player dies. This is all we need to code. Let's connect things in Unity. Select the player and go
to the Prefabs folder. Drag the explosion prefab
into the empty slot. Do the same for 3
m. Let's try it. With this, throw a meteors
and explosions spam. The same happens when we
destroy the spaceship. Great. In the next lecture, we create animations for the spaceship and
transitions between them.
25. Damage Animation and Transition: Hello everyone. In this lecture, we create this
blinking animation when the player takes the image. First, go to the
Animations folder, create a new folder
for the player. Animations. Select the player. Then create animation, makes sure that it is
in the correct folder. The animation will
be called idle. The sprite we need is
in the sprites folder. Usually in idle animations, there is some movement of
the object we animate, but in this case, we will use just
one default sprite. Idle animation will be
a aesthetic sprite. So select the player, plays the sprite
at the beginning. And I will place the same
sprite at 1 s on the timeline. Now, let's create
one more animation. I will call it damage. Then use the white sprite. I will change the
sample rate to 30. Then again, use the same sprite, place it at the 0.06
on the timeline. Since the sample rate is the duration will
be a bit longer. You can expand the
distance between frames to increase the
duration if needed. Now, you can see the animation, just a white sprite. Usually to preview animation, you can use the preview
and play buttons. Next, we need to disable looping for the
damage animation. Then go to animator,
select the player. Now you can see idle
and damage states. We need to create the
transitions between them. The oranges state is
the default animation. Right-click on the
idle state and create a transition
to the damaged state. Do the same in
opposite direction. Click on the transition
arrow to see some settings. To transition from
one state to another, we use exit time or conditions. For this transition, we
will use conditions. So we need to create parameters, open the Parameters tab. Then we can add four types. In this case, we need a trigger. Let's call it damage. We will activate this
trigger through a script. Now we can disable exit time. We need immediate transition. So set this to
zero or condition. Let's use the trigger. We made. Note that you can have more parameters and use
them as conditions. Now, both conditions need to be made for the
transition to happen. Of course, we need
just the trigger. So delete this example, then select the transition
from damage to Idle. Here we will use exit time
instead of conditions. If we set the exit time to one, that means the transition
will happen when the damage animation is
completed. If you e.g. set the exit time to 0.5, then the transition
will happen when 50 per cent of the
animation is completed. Set this to one. The transition duration needs to be zero, for instance, change. Now, when we completed the
settings in the script, we need to activate the damaging trigger when
a player takes the image. Open the player stats script. First, we need to create an Animator component in the tech damage function
to activate the trigger, we use any data set trigger. In parenthesis, we write
the name of the parameter. Make sure you spell
it correctly. Let's try it. Don't forget to
assign the animator. We take the image and we can
see the damage animation. However, if you
take them multiple times in a real short
period of time, we can simulate
that at the moment. But in a situation when multiple bullets
hit the spaceship, the animation would
go into spam mode. The spaceship would be in the damage animation
all the time. So let's prevent that
in the script at one bolt variable and
set the value to true. Then we first check if
that variable is true. Then activate the Animation. And here we also need to
add an anti-spam function. Let's create an
enumerator anti-spam. Here we set the ball
variable to false so that we can activate
the Animation. Then we wait a certain
amount of time. I will set the
waiting time to 0.15. Then reset the ball variable. To call this function, we use start coroutine. Now, when the player
takes the image multiple times in an
interval of 0.15, the animation will
be called only once. You can increase the
interval, if you like. And that's it for this lecture, we have animation transitions.
26. Shooting Enemy: Hello everyone. In this lecture, we
create a shooting enemy. This is a great opportunity
to implement knowledge from previous lectures like movement,
shooting and animations. But also we'll learn
some new stuff. So it will be a bit
longer lecture. Let's start. First for shooting enemies, we use a purple spaceship. Change the name, then
set the layer to enemy. Increase the order in
the sorting layer. Remember, all enemies
go to order five. Then let's add components, rigid body 2D, and
set it to kinematic. Instead of using
polygon collider 2D, we will use two books
colliders and then merge them. So add a box collider 2D. Click on the edit
collider button. Let's change the shape. Then add another
box collider 2D. Again, change the shape. This is not super precise, but its performance efficient and it will function just fine. To merge colliders, we
use composite collider 2D select used by composite
for every collider. Notice that we
have one collider. There are no lines
that intersect. Then select the Is Trigger
option in composite collider. Now, let's create
shooting points. I will call this left Canaan. Move the object to the
shooting position. Then duplicate it and
rename it to write Canaan. Place it on the other side. Let's create a script. I will call it purple enemy. Select the enemy
and add the script. Open it. First. This class needs to be a child
class of the enemy class. Just to remember, the enemy
class has some variables and functions that will be
inherited by all child classes, including the
purple enemy class. In the purple enemy script. Let's create
additional variables. First, we need a
float variable speed. Then we need should, dimer and shoot interval. Let's create the
transform variables for shooting positions. Then create a game object
variable for the bullet prefab. Let's all variables we
need to move the enemy. Let's use the rigid
body variable that we inherited from
the parent class. Set velocity vector to
down multiplied by speed. To shoot, we need to create a timer in the update function. First, we increase should timer by Time.deltaTime every frame. Then we check if that timer is greater or equal to
the shooting interval. If that is true, then we can shoot. Of course we use the
Instantiate function. Instantiate bullet prefab
in the left can and position use quaternion
identity for rotation. Then we can copy and
paste this code. Just replace the left Canaan
with the right Canaan. After death, we
just need to reset, should timer to zero. Now, the enemy can
move and shoot. Next, let's resolve when the enemy collides
with the player. Since we are using a trigger, we need the On Trigger
Enter to the function. First, we check if
the object is at player using the
compare function. Then through player states, we can call the player
take damage function. Use the damage variable, which is inherited
from the parent class. Then we instantiate
the explosion prefab. After debt. We destroy the enemy. So everything we
did in the script is known from previous lectures. That is why I go a
little bit faster. Now, let's override
virtual functions hurt and that sequence later, we will add animation in
the herd sequence for now, in the death sequence, which is called when enemy
health is below zero, instantiate the
explosion prefab. Then destroy the enemy. Of course, enemies
may not collide with the player or the player
doesn't destroy the enemy. That means the enemy will go off the screen to destroy objects
that go off the screen, we use the own became
invisible function. Let's save this and go to unity. In unity, we need
to set variables. I will set Health to three. Then we need rigid body. Damage upon collision
can be one. Then use the explosion
prefab that we made. Set speed e.g. to five and shoot
interval to one, which means 1 s. Let's connect a left and
right shooting points. Then we need to create
a bullet prefab. So let's go to sprites. We have this bullet sprite. Rename it. It's too big. So let's decrease the scale. I think that this is good. Let's change the
order in the layer. Then let's create a new
layer for collisions. I will call it
enemy projectiles. Set the layer to
enemy projectiles. Let's go to the
collision matrix. Enemy projectiles
need to collide with the player, ignore
other collisions. Now, let's add a Rigid Body 2D and change the
type to kinematic. Then add circle collider 2D. We can decrease
the radius a bit. We need to create a script
called Purple bullet. The script to the bullet. Open it. We need damage and
speed variables. We also need a rigid
body 2D variable. In the start function, Let's get the rigid
body 2D component. The bullet needs to go down. So set velocity vector to
down multiplied by speed. We don't need the
update function. Let's damage the player when
it collides with a bullet. We use the On Trigger
Enter to the function. I think that in Unity I forgot to set collider
is a trigger. We will do that later. Here as usual, we
check for the player, then call the player
take damage function, then destroyed the bullet. We also use the own
became invisible function to destroy the bullet when
it goes off the screen. That's all for the
bullet script. In Unity, set damage and speed also enable the
Is Trigger option. We can create a bullet prefab. Delete one from the scene. Now select the enemy and
use the bullet prefab. Let's try it. Mode the enemy up
and press play. It works nice. Now, we need to create
animations for the enemy. We will need this
animation window. Select the enemy and
create animation. I will call it enemy idle. Use the purple enemy sprite. Let's create one more animation
and call it enemy damage. Use the white sprite. Set samples to 30, and again, use the white sprite. Go to the Animations folder, select enemy damage
and disable loop time. Now go to the animator tab. This is good practice for animation transitions that we covered in previous lectures. Let's create two transitions. Then create one
parameter damage. Select the transition
from idol to damage. Use the parameter
is a condition. Duration is to be zero and disabled exit time
for another transition, leave time and just change the duration of
the transition to zero. Go to the purple enemy script. Actually, let's go
to the enemy script. Usually all enemies
use an animator. So let's create one
animator component. Then go back in
the herd sequence, activated the transition
with the trigger. In Unity, select NME. We need to assign the animator. Scroll down and you will see it. Expand this and
use the animator. Let's try it. It's working nice. We can also create an anti-spam
function for the enemy, just as we did for the player. But I will show you a
different approach. In the emitter tab under layers, you can see the base layer, his index is zero and we
will use it in the script. Then select the
enemy damage state. In the Inspector, you
should see the tag field. Use the IMG tag. Back to the script. First, we check if the
animation is already running. We use the function, get current animators state in with the index
of the base layer. Then check if that
animation has a tag. In this case the mg. If that is true, that means the animation is
currently running. So just return, don't
activate it one more time. This is a bit different
approach for the same thing. That's all we need to code. There is just one
more thing to do. We need to create a
purple enemy prefab. And now we're done. We have shooting enemy. See you in the next lecture.
27. Green Enemy: Hi everyone, Welcome to
the enemy challenge. Your challenge is to create
a second enemy spaceship. The spaceship needs to have a
similar behavior to meters, just a bit faster and
width to damage animation. This is a good
practice to remember everything we learned in
the previous lectures. Okay, I will select the
green enemy prefab. You can see that he needs
to be on the Enemy layer. The sorting order
needs to be five. Maybe if you want
to make sure that spaceships are in
front of meteors, you can increase it or
decrease meteors to four. You can see we have the
green enemy script. We have kinematic, rigid body. We're here to colliders
and a composite collider. And we have an estimator
for animations. Now open the script. First. The enemy needs
to be a parent class. We use one variable
speed is usual. We set the speed in
the start function. For collisions. We use the On Trigger Enter
to the function, then we use the hurt
and that's sequences. Basically, it's a
copy paste code from the previous lecture. I just deleted the
shooting apart. In the end, we have
the own became invisible function in Unity, Let's see animation transitions. We have two animations
and transitions, just as in the previous lecture, settings are the same. Now, when we have
two enemy types, let's create an enemy
spanner in the next lecture. See you there.
28. Enemy Spawner: Hello everyone. Now, when
we have any prefabs, let's create a spanner. First, let's create
an empty game object. Reset the transform component. Next, let's create the
enemy spawner script. The script to the object. Open it. Since this is a spammer, we can use some code from
the meteors partner. Remember, first, we
need to ensure that objects through spanned
outside the screen. So go to the meters partner. Let's copy this part that we
use for spawning positions. They also need to copy paste
the set boundaries function. Nice. To organize the script, let's use the attribute header
and name it enemy prefab. Let's use an array of game
objects for enemy prefabs. Then we need a
float enemy timer. Then use the attribute space to create space
between variables. We need a float variable,
enemy spam time. Then let's create a function
that will spawn enemies. First, let's increase the
timer by time, delta time. If that timer is greater or equal to the
inter-response time, then we need to spawn enemies. Since we have two enemies, let's randomly pick one. Use random that range between
zero and enemy length. This will ensure
that the code works with any number
of enemy prefabs. Then instantiate the enemy
using the random pick index. For position, we use new
vector 34 x-coordinate. Use random that arrange between maxilla left and max
right positions. For the y coordinate, let's use y position. And for the z-axis, we can use zero. This is the same
procedure as before. For rotation, we can use
quaternion that identity. After debt, we reset the timer. Call this function in update. That is all we need to code. Let's go to unity. Let's assign enemy prefabs. Then we can spend
an enemy every 2 s. Let's try it. We can see the purple enemy. And we can see the green enemy. Nice. That's all. See you in the next lecture.
29. Win Condition: Hi everyone. In this lecture, we
create win condition. The idea is that
the player survives a certain amount of time and
after death, the game ends. First, let's create
a new game object. Then we can create a script. I will call it a win condition. The script to the
object and open it. We need a float dimer. Then we need a float
possible when time variable. We also need an array of game objects that
we will use for spawners in the update function. And let's increase the timer by Time.deltaTime every frame. Then check if that timer is greater or equal to
possible when time. If that is true, that means that the
player has survived and we can deactivate spawners. We use the for loop counter. I is zero. We go through the loop
while I is less than its founder length and
increase by one each step. In the loop, we deactivate
this partner with index i. Just the more
explained this loop, let's say we have two
spammers in the array. Indexes are 0.1. The length of the array is two. So counter I will be
zero at the start. Then we check if zero is less than the length of the
array, which is two. In our example, this is true. So then we deactivate the
spammer with index zero. Then increase I by
11 is less than two. We deactivate this
partner with index one, increase I by one. Now two is not less than two. We exit the loop. After we deactivated spammers, some of the enemies are
still on the screen because those enemies can
still destroy the player. I call this a
possible when time. We need to create a function that will check if the player is alive after all enemies are
of the screen or destroyed, then we could show a
win or lose screen. All that we will do
through game manager. I write this code in comments
to remind you and myself what needs to be done in another script and
then call it here. In the next lecture, we will create a
panel controller that will manage win or lose screens. For now, go to Unity. Let's say that the possible
when time is 10 s, then we need to add
spammers to the array. We have enemy and
meteors, pounders. I will just organize
the higher here a bit. Let's test it. Survive 10 s and then enemies
should stop spending. I will try not to die. Grid. You can see that's
bounding stopped. The next step is to create
a win and lose panels, which we do in the next lecture. See you there.
30. UI Panel Controller- Text Mesh Pro: Hi everyone. Let's create
win and lose screens and a script that will have functions to activate
those screens. First, let's create a new image. I will call it a panel. Note that this image doesn't
go into the safe area. Next, we can use the
square is a source image. Then we need to stretch it. Then change the color. I will use Blake. And let's make it
a bit transparent. Then let's create a new image. It needs to be a child
object of the panel. I will call it a win screen. For the source image, we will use this
large panel sprite. Note that I already
did nine slice. Check the Health Bar lecture for more information about
the nine slides. Let's use the sprite, makes sure that the
image type is sliced. Then we can change
the dimensions. The image needs to be in
the middle of the screen. Let's see how it looks
in the simulator. This is good. You can
change it as you wish. Now, let's add text
to the vein screen. Select text Mesh Pro. This is the first
time we use text, so we need to import
text Mesh Pro. Let's rename it to when texts. Then let's adjust
the right when. This is not the final
look of the windscreen, this is just a sketch
and placeholder. For now, it's about
functionality. And later we will
add more texts with three buttons and
other UI elements. Then let's duplicate windscreen. Called this loose screen. Change the text to fail. Okay, now we have basic
win and lose screens. Let's select the panel and now add the canvas
group component. Canvas group has some cool
options that we can control. E.g. we can change the Alpha settings for
all objects in the group. These screens will have buttons. So in order to press them
and interact with them, we need to live interactable
en bloc ray casts enabled. We can set the Alpha to zero. Then let's also disable
win and lose screens. Let's create a new
empty game object. I will call it a
panel controller. Then let's create a
folder for UI scripts. Create a new script. Panel controller. The script to the
object and open it. First, we need the
canvas group variable. Then we need to game
object variables. One for windscreen and
another for Louis screen. We don't need the
update function. Let's create a function that will activate the windscreen. First, we set the
alpha value to one. Then we activate the windscreen. Let's also create a function that will activate the screen. It's a similar procedure. For now. That's all we
need to code in Unity. Let's connect components and
objects with the script. We need the canvas group
component from the panel object, then connect the screens. Now the question is
when and how to call functions that will
activate those screens. Maybe you are thinking, let's connect panel controller
and when condition. Don't do this, instead of making a direct
connection between them, we will create a game manager. This is a kind of
preparation lecture. In the next video, we connect all of this through the game manager. See you there.
31. Game Manager: Hello everyone. In this lecture, we create a game manager. Again, Manager is a script that controls important aspects of the game and it is used in many other scripts to help
run the game correctly. First, let's organize
the higher here a bit. Let's create a new
empty game object. I will call IT managers, since we will have different
managers in the game. Next, again, create a
new empty game object. I will call it End Game Manager. This manager, as his name says, will be responsible
for controlling functionality when the level
ends or the player dies. Let's also create a manager's
folder for scripts. Create a new script, and call it End Game Manager. The script to the
object, and open it. Since this game manager will
be used in many scripts, we need to create a static
instance of this class. So we've write public static, the name of the class, which is an in-game manager. Then we choose a name
for this instance, I will call it end manager. This is just an empty variable. Now, we need to assign value
in the awake function, which is called before
the start function. We set the instance and
manager to this class. Now everything that this
class contains variables, functions, and so on. We can use it with the
end manager instance. Note that the keyword static gives us easy access
to other scripts. What does mean easy access? I will show you a
very simple example. Let's create a public
ball variable game over. Now let's go to the
player stats script. When the player health value
is less or equal to zero, that means that
the game is over. So we can just write
End Game Manager, that end manager, that GameOver and set the
variable to true. Note that there is
no direct connection between the players States
and GameManager scripts. I don't need to use get component or connect
anything in Unity. This will function as it is. Now. Let's add functionality
to the end game manager. We need to functions
when game and lose game, makes sure that they are public. So we can call them
in other scripts. If we need them. In the game function, we need to activate the screen, unlock the next level, save the score, and so on. For now, let's just
activate the screen. Let's go to the panel
controller script. Remember, in the panel
controller script we made functions that
will activate screens. So we need a way to use them
in the game manager script. Now, I will show you the
structure we are building. You know that in
the scene we have End Game Manager and
panel controller. The controller has
some functions that control UI elements. We also have the vein
condition object in the scene. In the win condition script, we need to call functions that
will activate UI elements. We also have a
player in the scene, and we also need to activate UI elements from the
players test script. We could directly connect
player controller with those objects in Unity inspector
or use getc component. But we want to avoid that. It's not practical. And as your game expense, there will be more and more
objects and everything will be directly connected with
everything. It's a mess. We just need to connect
the controllers, in our case, panel controller
with the game manager. And since the manager is static, it has easy access
to all scripts. Notice the advantage,
everything goes through one channel and that
is the game manager. The trick is to efficiently connect the manager
and controllers. Instead of the manager
looking for the controller, the controller will register
itself to the manager. So in the manager script, let's create the panel
controller variable. Then we can create a
public function for registration, register
panel controller. It will take one parameter, panel controller in the function set the panel controller
variable to PC. Now go to the panel
controller script. The start function, let's call the registration
function that we made. To the function, we
will pass this class. Notice how this is easy because the manager is a static class. Now in the manager, we can use the panel
controller variable to activate UI elements. Now, let's create the
result game function. If the game over is false, then we can call the win game or else we can call
the Lewis game. Now go to the vein condition. When the time expires, we deactivate this
pounders and we could directly call the
result game function. This would function correctly. There is no error here, but we have a small problem. When we call the
resolve game function, there is a chance that there are still some enemies
on the screen. Those enemies could
destroy the player. So we need to
introduce some delay between the activating
these partners and calling the result game function back to the manager
script or delay, we use co-routine functions. Let's create the eye enumerator resolve
sequence function. We can wait e.g. 2 s. Then we will
call the result game. Now create a public start
resolve sequence function. Here we use start correlating to call the eye
enumerator function. This is the function
that we will call in the wind
conditions script. Note that after
the timer reaches possible when time this
condition will be met, every frame, it will
constantly run this code. So we just disable this game
object after the first run. Nice, Let's try it. We need to survive 10 s. Then the spinal
nerves will activate. And after that, we
have two extra seconds before the win or lose
the screen appears. It depends. Did we survive
those two extra seconds? As you can see, it works. Now, let's go to the
player stats script. After the player is destroyed, we also need to call
start result sequence. To avoid multiple calls
from different scripts. Before we start the curtain, let's stop the current. If it's already active,
use stop carotid. We need to pass a string, but we can use a name of n,
choose resolve, sequence. Let's try destroy the player. And we should see
a loose screen. Great, This is all
for this lecture. See you in the next one.
32. Singleton Pattern: Hello everyone. Let's upgrade the end
game manager script with the Singleton pattern. A single term pattern
means that can be only one object of the same
type in the whole game. That means we should have only one end game manager
in the entire game. This is very useful
for static classes since we need to be
careful about performance. At this point, we
have one scene. Let's call it a level one. Now, duplicate it and
call it a level two. When we go from one
scene to another, all objects from the previous
string are destroyed. E.g. we go from level
one to level two. All objects from level one
are destroyed and unity, although it's new objects
that behave in a level to connecting all
these things together. We get a game. When a player plays the
game multiple times, he can start it on
different levels. The idea is to somehow preserve the manager from the level
where the players started. By default, we have
some objects in every scene and every sin has the end game manager object. So let's go to the end
game manager script in the awake function. First, we check if
the instance is null. Then set the instance
to this class. Then we use that don't
destroy onload function. We don't want to destroy
this game object. Just to show you, I
will run the game. Click on the pause button
and you can see that the end game manager
is placed in another scene called
don't destroy onload. Let's say we start at the game. On the first level. We go to level to
all objects except the end game manager
will be destroyed because of the don't
destroy onload function. This manager will go
to the level two. But now we have
two game managers, one from the first
level and another day it was by default in
the second level, we need to destroy one from the second level in the script. Use else, which means the end manager
instance is not null. Then destroy this game object. So the GameManager from
level two will run the awake function
and the instance of end manager will not be
null because it will detect it from the manager
that came from level one. So in our example, the manager from level two, we'll run this part of the
code and destroy itself. And that's it. We created
a singleton pattern. In the next lectures, we will learn how
to switch between, since See you there.
33. Change Levels/Scenes: Hello everyone. Let's see how we can
change since using buttons to organize
the hierarchy, let's create a new
empty game object. Call it controllers. We can place the panel
controller under it. Now let's create a new object and call it button controller. Then create a new
C-sharp script. I will call it also a button Controller at the
script to the object. And open it. First to change,
since we need to use this thing
management namespace, we can delete default functions. Now, let's create a public
function load level stirring. It takes one string parameter. I will call it a level name. To load another scene, we use Scene Manager
that load scene. And then we will
paste the string, which will be the
name of the level. We can also load new scenes using integers and build index. So let's create a public
load level int function that takes one
parameter level index. Make sure that functions
are public. Here. We also use Scene
Manager that load, but we pay is the
integer level index. Where to find build
indexes for levels. Go to Unity file
and build settings. Here you can find, since that will be
included in the game, our level one is included. And here you can see the
build index is zero. We can go to the Scenes folder and add a level two to the belt. You can see that
his index is one. So to load the level by index, we would pass one
of these numbers. Great. Now let's create buttons so we can call the
functions we made. First, let's select
the panel and increase Alpha so we can
see what we're doing. Then right-click on the
windscreen and create a button. I will call it home button. We can delete the text. Let's change the source
image for the button. Use the home icon sprite. Click on the Set
native size button. And let's change
the anchor preset. Choose center bottom. We can move it a bit down. This looks fine for now. You can see that the
button has onclick event. This is called when we
click on the button. Let's add a new event. Idea is to call functions
from the button controller. So let's drag the
button controller. Then we choose a function to call from the button
controller script. Let's use the load level
of string function. Now we can write the name of
the scene we want to load. Later. This button will lead
to the main level selector, which we don't have now. So use level two. You could also use
the function alone, level int and write
the build index. But in this project, we will mostly use
the string option. We will use a loading
with the bill, the index, just to
restart the level. I just wanted to show
you both options. Next, let's enable a loser
screen and create two buttons. First we'll also be home button. Change the position. Duplicate it and call
this button retry. Change the icon. Now we can add the onclick
event to the buttons, to the home button. Let's add a load level
of string function. For now, leave it empty. We will change this later. Use the same function
for the retry button. Here you can write the
name of the current scene, but you don't want
to write strings for every retry button
in every level. It's a lot of work. So let's go to the button
controller script. Create a public restart
level of function. We use Scene Manager
that load scene. And then we use the build the index of the
currently active sin. So right, Scene Manager
that get active seen, parenthesis, that built index. This will restart any level
in which the player is. So for the retry button, use the restart
level of function. We are not done, but let's try it to
see potential bugs, disable the screens and change
the alpha value to zero. Let's try to win. I will speed up time a bit. You can see the windscreen
and the button. Press it, and we should
be in a level two. It works nice. Let's exit play mode
and start it again. Now, let's try to
destroy the player. We get the Lewis screen. Let's restart the level. I will click on the pause
button to show you one problem. You can see that the
variable game over is still true even when we
restarted their level. It's because the
end game manager is aesthetic Singleton and all
variables kept their values. So now if we continue playing and get to
the end of the level, we will still get
the wrong screen. Luckily, there is a
simple solution to this. Go to the player stats. In the start function, we set the value to false. Now, every time we
allowed levels, the variable is set to false. We can do one more thing in
the wind conditions script. In the update function, we can check if the game
over variable is true. Then just return and don't
execute the code below. That means that the timer will stop when the player
is destroyed. Let's try it now. Destroyed the player. Restart the level. Tried to win it
after the restart. And we get the wind screen. Now everything works. Of course, we don't want an instant transition
between levels. We need some kind of fading effect which we create
in the next lecture. See you there.
34. Fade Between Scenes: Hi everyone. Let's create a nice fade effect
between loading. Since I will create
this effect on a separate Canvas and also
read the Singleton pattern. So let's create a new canvas
and call it Canvas fader. Change it to scale
with screen size. We can also change the
reference, the resolution. Then let's create an image. I will call it background
or the source image. We can use the square, then stretch it and
change color to black to make sure that these black image
is visible in front of other elements
from another canvas. We need to increase the
sort order of this Canvas. Then select the image and add
the canvas group component. Idea is to change the Alpha value to
create the fade effect. Of course, here we don't have buttons and other
interactive elements. So we can uncheck
the interactable and re-cast options to
change the Alpha value, we could use animation, but for mobile devices, animating UI elements is expensive and not
good for performance. So the better option is to use scripts and change the
value through code. Let's create a new
C-sharp script. I will call it fade canvas. Add the script to the
Canvas fader, and open it. First. Let's create a public static
paid Canvas Instance. Then let's create a
singleton pattern, just as we did for
the GameManager. This is a good practice
to repeat some things. Now, we need variables. First minute, a canvas group. Then we need a float,
change, a value. Float, wait, time. And bold, fade started. That's all variables we need. We can delete the
update function. To create a fade effects. We will use coroutines. Let's create the eye
enumerator fade in function. This function will turn the
black screen transparent. First, let's set the
fade started to force. This variable will be true only when we use the fade out effect. Then we use the while loop. While the alpha value
is greater than zero, we need to decrease it. So let's decrease
the alpha value with the change value variable. Then we need to set
the speed of change. After each change, let's use the wait 4 s function and
the wait time variable. We can call this
function in the start. Let's see what we made in Unity. Use the Canvas group from
the background image. The change value variable
needs to be a small number. I will set it to 0.04. Wait, time can be 0.01. Let's try it. You can see that we have a
nice fading effect. If you want to make
it the longer we can decrease the change value
or increase with time. You will see that the effect
last longer, maybe too long. So I will make it shorter. Back to the script. Now, let's create
the opposite effect. The image should go from
transparent to black. Create a new eye
enumerator function, fade-out string, which
takes one string parameter. Now the faith started
variable will become true. Now, while the alpha
value is less than one, we need to increase it. Then we also use wait 4 s. We will exit the slope when the alpha is
one and the image is black. Then we need to loud level. Let's include this scene
management namespace. Then we can use a load scene and pays
the string level name. After that, we again start
the fading effect in the new scene and the background image is
going back to transparent. We can add some wait time between loading
and fading effect. Remember that this object
is aesthetic singleton, so it will not be destroyed
when changing scenes. To make sure we don't
get multiple calls, we can check if fade started. If that is true, then use yield break. Now let's create a public
function bather load string. Here we will start
the fade-out effect. Then go to the button controller that we made in the
previous lecture. Remember, when we press buttons, this function is called
to load a new level. Instead of floating,
since directly, let's use the function
from the faith Canvas. In Unity. Just check that your home button is using the function from the
bathroom controller. We did this in the
previous lecture. Before we try it, Let's duplicate this level one. So we have the same components. Delete old level to Rename
duplicate to level two. Later, when we create all the necessary objects that
need to be in every scene, then we will have a template, sin and the prefabs from which
all sins can be created. For. Now, we copy paste
scenes to test them. Let's try. We should see the fading effect. Try to pass that level. Then we should see the fade-out
effect and then fade in. Again. It works. Now I have
one-minute challenge for you. Try to create a fade-out
function that will take one int parameter
instead of string. The solution is quite simple. We can just copy,
paste the code and set that load scene
takes level index. We also need to create a public function to call
the integer version. The button controller script. We use this function
to restart the level. Again, instead of
calling it directly, let's use the function
from the fader. We don't use this
function anywhere, but let's change it. Maybe you will use it
somewhere in your game. It needs to use the integer
version from the fader. Let's try to restart the level. We can see the effects. That's all for this lesson. In the next lecture, we create a loading screen.
35. Loading Screen: Hi everyone. In this lecture, we create a loading screen. Let's right-click
on the canvas fader and create an image. I will call it a
loading background. We need to stretch it, then change the color. Now, we need to
find the **** bar because we will copy,
paste some elements. The Health Bar, and make it a child object of the
Canvas page there. Let's delete some
extra elements. We don't need the icon holder. Now, we can place the loading bar in the
middle of the screen. Let's increase the size a bit. It needs to be a child object
of the loading background. This looks fine. Let's go to the fader script. First, let's include
the UI namespace. Then we need one
game object variable called a loading screen. Then we need one image,
the loading bar. Now find the fade-out function. We can comment out this
code because we will use the async cooperation
to load levels. The async operation gives
us the option to load level is a background process and we can keep tracking
the progress. Through the async cooperation, we get access to the
progress which goes 0-1. When the level is fully loaded, the progress is not
actually one is 0.9. This 0.1 difference is reserved for the bull variable,
allow sin activation. We can control that variable. And if we set it to false, even if the next level is fully
loaded in the background, the progress value
can't get over 0.9 and we can't go
to the next level. When we set this variable to true and the level
is fully loaded, the value is one, and we can go to a new level. We have another important
variable is done. This variable is true when
the progress bar is one, which means fully
loaded level with allowed sin activation
and its force. In any other case. We will use these variables
to create a loading bar. First, we create an async
operation variable that we'll get the value through Scene Manager that
allowed seen Async. This will load a new
scene in the background. Then we set sin
activation to false. So we have control. We need to activate
the loading screen. And we can set the loading
bar fill amount to zero. Now we use a while loop. While the async operation
is done is equal to false, which means that the
level is not fully loaded or activation
is set to false. We set the fill amount to
async cooperation progress. Since the value goes to 0.9, we need to divide it by 0.9. Here we don't need to use a
wait 4 s. We can just return null between those
lines of code. We can check if the
progress is 0.9. Again, that means that the level is fully loaded in
the background. Then we allow sin activation. At that moment the is done, variable will become true
and we exit the while loop. We can delete this line of code. Now, we can copy the code. In another fade-out
function, paste the code. Just to replace the level
name with the level index. We need to do one more thing
in the fade-in function, we need to deactivate
the loading screen. Now go back to Unity. Before we connect
objects with the script, Let's rename them so we don't confuse them with
the real held bar. Then use the loading background as the loading screen object. For the loading bar image. Let's use a loading. Let's try it. When this level. Then go to the next. Notice that because
the level is too small and we are testing on PC, the loading is to paste
and we can see it. But on a mobile device, you would see progress
on the loading bar. One more trick, if the fader Canvas is covering
your view in the scene, you can hide it
with this button. And that's all for this lecture. See you in the next one.
36. Upgrade/Fix Fade Effect: Hello everyone. This is Mario from the future. Later in the course, I noticed one bug with
the fading system. It's very specific,
but we need to address it and fix it with just
two lines of code. If you see something
in Unity or in the code that we didn't
do yet. Don't worry. This is because I
recorded this video after a few episodes and decided to place it
here in the course. I will quickly show you the bug. Here I placed to debug logs, one for fading and one
for fade-out effect. Select the Canvas Fader. Now, I will just make
the fade effect longer. It will be easier to
replicate the bug. Also, I will use, since that we make
in the future, it will be easier to understand. I have a label
oscillations seen. This button starts
the fade-out effect and leads to a new level. At first, you can see
everything works. But there is a case if I
press the button and activate the fade-out function while
the fade in is still running, then two while loops
will fight each other. Let's press the button while the fading effect
is still active, you can see it in the console. At the same time, we are decreasing and
increasing the alpha value. Because of this, we can go to the next level because the
screen will never turn black. We can fix it in several ways. My way is to go to
the fade-in function. In the while loop, we can check if the Fed
started variable is true. That means we activated
the fade out, then break and exit
from the loop. That is all we need to do. Now, if I press the button, the fading effect will stop and the fade-out effect
will take over. If you want different
behavior, e.g. that fading effect must finish. Then you can check in the fade-out function
for the alpha value. If it's not zero, then break and exit
this function. Now we can press the
button but nothing will happen until the
fading is finished. It's up to you to choose the
best option for your game. Thanks for watching and see
you in the next lecture.
37. Font Creation: Hi everyone. In this lecture, we go through the
process of creating font assets for our
texts mesh proud text. I will drag the fonts folder
from the other screen. You can find the link to the download page in
the resource folder. You can use the same font
or any other that you wish. Now, let's right-click on the
canvas and create a text. I will quickly rename it. You can see that this
is the default font. We can try to
change it directly, but nothing will happen. We need to create a font
asset to replace the font. Go to Window, Text mesh Pro
and open font asset creator. As a source font file, use the font you want. You can see some settings, we can leave default ones. Maybe the most important
setting is rendered mode. For this font, the
default setting is good. If you use pixelated fonts, arrest or mode is better. So it depends on the font views. You can try different options. Then click on the Generate
Font Atlas button. Then we can save the font asset. Now, drag the asset Ve created
to the font asset field. And you can see the new font. You can play with
some settings to export the text
Mesh Pro package. We can also replace
the font that we use for the win
and lose screens. Delete the test text. After you enable all objects
and set Canvas alpha to one, you can see the result. Nice. That is all for this lecture.
38. Score System: Hi everyone. Let's create
a scoring system in which a player gets points every
time he destroys enemies. We will show the score in
the upper-right corner. So it needs to go
in the safe area. Right-click on the safe
area and create the text. Let's change the anchor preset
to the upper right corner. Hold Alt and Shift and click. Let's change the position a bit. We can expand the text
area a little bit. We can change the font. This font asset we created
in the previous lecture. Let's change the alignment. I will choose the middle, but maybe you can leave
the left alignment. This also goes to the middle. Now, let's write
a score of 1,000. Notice how the text goes
in the next aligned. To prevent that, we need
to disable overlapping. Let's expand the text
area a bit more. Of course, you can change
the font size if you want. I will leave it as it is. Let's go to the end
game manager script. We will use the text mesh per package components
in the script, we need to include
the DNS namespace. Then let's create a text
component variable. Now we need a reference
for this text. Let's create a public function to register the score text. Now we can go to unity to
create a new C-sharp script. I will call it
score registration. The script to the text
we created before. We don't need the
update function, we need the DNS
namespace. In the start. Let's create a text component. Since the script is on the object that has
a tax component, we can use Get component. Then we can register the text
to the end game manager. It's a good idea to
set the text value to default one
with a zero score. Go back to the game
manager script. Now, we can create an
int variable score. Let's create a
function that will increase the score
and update the text. It needs to take
one int parameter. First, we increase the score. Then we update the text. Since the score is an integer, we need to convert
it to a string. Great. The idea is to
call this function every time the
enemy is destroyed, Let's go to the enemy script. In the enemy script in the
debt sequence function, which is called every
time enemy dies, we call the update score text. Of course, we need to pass
one variable to the function. So let's create one int
variable score value. This value will
increase the score. Note that this is all done
in the parent enemy class. We need to update child classes. Let's start with
the meteor script. When we override
that that sequence, we need to call the
base that sequence. This we'll call everything
from the base class. Let's do the same for the
purple and green enemies. Go to unity. In the prefabs folder, select NME prefabs, and choose the score value
for each of them. I will go with ten
for all of them, but you can choose
different values. Let's try it. As we destroy enemies, the score increases by ten. Great. Of course, I would like to show the score and
the highest score on the win or lose screens. We also need to reset
the score after that, go to the end game
manager script. If you remember, we have
the win and lose functions. Here I mentioned we need to
do something about the score. We need to show the score, check for high score
for this level, and then reset the score. To do all of that, we need to know something
about saving and loading data, which we'll learn in
the next lectures. See you there.
39. Playerprefs Syntax: Hello everyone. This is a quick video explaining
the player prefs syntax. Using simple examples, we will see how to save and
load basic data. I created one example script. You don't need to write it. Just follow and try to
remember the syntax. Here I have three variables
that I want to save. Notice that I used three data types that we
can save with player prefs. And those are integer,
float, and string. So to save data, we
use PlayerPrefs, that set and then
choose the type. The first example, we use
set int in parentheses. First, we write the string key, which will hold
the value we save. You can name it as you wish. I chose int k, then we write the value to save, in this case example int. The same logic applies when a saving float and
string values. So how to load a saved values? We will use this case. I also created variables in which we will load
the saved values. To load the values, we use PlayerPrefs that get, of course, we can get
integer or float or string. In parenthesis, we write
the key to load values. So the key will load the
example int value we saved. Just make sure that
you correctly write the K If you miss some
lighters or something, this will not work. The second part in
parenthesis is optional. It determines the default value if we haven't previously
stored anything. In this case, it can
be any value you want. I just set it to
zero and nothing. To delete saved values. We use the Delete key
function in the parenthesis, we write the string key
that we need to delete. Also, there is an
option to delete all saved data with the
delete all function. Of course, when testing, deleting all saved data from
the code can be unpractical. So in Unity, we can go to Edit. And here we have the clear
all player prefs command. That is all for this lecture. Now that we know the syntax, we can create a
highscore system.
40. Save and Load Score/High Score: Hello everyone. Now that we know the
player pref syntax, we can create a save
and load system. The goal of this lecture
is to save the score for each level and
determine a high score. Let's go to the end
game manager script. We need to create one
function that will save the score and update the
high score if needed. So create the score
set function. Let's use player prefs set int. The key will be score combined with the name
of the current scene. In that way, every level
will have a different key, and that is what we want because every level has its own score. The value we save is,
of course, score. Then let's create one
into variable highscore. We use the get int value. The key will be highscore
combined with the scene name. The default value
needs to be zero. Then we check if the score is greater than the high score. That is true, then the score is a new high score
and we can save it. Use the highest score key and save the score
value for that key. The last thing we need
is to reset the score. Now, we need to
call this function in the win and lose functions. Just make sure you call it
before we activate screens. This is really important
for the next step. This is all we need to do
in the game manager Unity. I want to display the score and the highest score on the
win and lose screens. Let's select the panel and increase alpha to one so we can see what we are doing
enabled the windscreen. We need to organize this screen and add some texts components. Let's change the color and set the anchor
to the top middle. We can add extra
effects to this text. Enabled the underlay. I will use white color
with smaller opacity. Now you can play with the
settings and change the offset. I think this looks nice. Now we need the text for
score and highscore. Duplicate this text, rename it. We need to change the
anchors to the middle. Adjust the text area a bit. Of course we need
a smaller font. Change the text so we
have a better preview. The alignment needs to be left. We can also disable
overlapping if needed. Let's move it down. Then duplicate it. This will be the score. Change the color and rename it. Your mini challenge is to do the same for the Lewis screen. This is the final result. As you can see, I changed
the color for this screen. Let's disable them and
return alpha to zero. Let's create a new
C-sharp script that will be responsible for score display on the
win and lose screens. And open it. Delete default functions. We need to include the TM pro en scene management namespaces. Then create two texts variables, one for the score and
one for the high score. Then we use the own
enable function. This means the code will run every time we
enabled the object, and this script will go on the win and lose screen objects. First, we create a
local variable score in which we load
the score value. Use the get function. The safest way to write the key correctly is to copy paste it, go to the end game manager
and copy the score key. The default value can be zero. Now let's update the
text with that variable. Do the same for the high score. Just make sure you
copy the correct key. That's all we need to code. Let's go to Unity. Add the script to the
win and lose screens. Now we need to set up a reference
for the text variables. Use the high score and score text that we created earlier. And that's it we can try. You can see the score and
the highest score. Now. It's then, let's play it again. You can see updated values. Maybe the screens are too small, so feel free to change
the dimensions. See you in the next video.
41. Scene Preparation: Hi everyone. In this lecture, we prepare sins so that we can easily create an opening scene, a layer of selections
scene, and new levels. This is just preparation,
nothing special, but we need to do
that so we can be faster and more efficient
in the next lectures. First, we need to
create Prefabs, select the managers,
spawners in controllers. We can select the win
condition Canvas and the player drag them
into the Prefabs folder. Save this scene with Control S. Go to the Scenes folder. We are in a level one, so duplicate it, rename it
to start screen and open it. This will be the first scene the player sees when
entering the game. We can delete some objects. Let's delete spammers, pen or
controller when condition, everything that's connected
with the virtual camera. Then the player in
a virtual camera. Let's also remove the cinema
machine brain component from the main camera. I will use one text
from the Canvas. This will be the winner. Thanks to use it, we need to unpack the prefab. Now I'm drag the text
under the safe area. We can delete the panel. We can also delete the
score and health bar. Let's rename the text. This will be name of the game. Expand the text area, increase the font, and change the anchor preset to top middle. This is a good position since we're not using cin and
machine in virtual cameras. Let's select the main camera
and set the size to five. Let's see how it looks. Not bad. Let's change the
color of the text. The vertex color
needs to be white. Now enabled color gradient. I will use a
horizontal gradient. The first color will be yellow, the second color will be orange. Great. Let's save the
scene and duplicate it. Called the new sea level
selection and open it. I will just change the text
so we can recognize it. This is a level of selection. Of course, we will
polish and add features to these things
in the next lectures. Remember this is just
a small preparation. Save the scene and open
the build settings. Now, let's add new
things to the build. Change the order so that the start seeing
is the first one, then level selection
and then levels. Okay, that's all for now. In the next lecture, we finished the start seeing.
42. Start Screen (Menu): Hi everyone. In this lecture, we implement the tap to play
mechanics in the start sin. So make sure you
open the star to see and then right-click on the
canvas and create an image. Call it tap to play trigger. We need to stretch it. Then set the alpha
value to zero. Now let's add the event
trigger component. We use it to create
a new event type. You can see some events, e.g. pointer down is when we
press on the screen, more precisely on the
transparent image we created. Of course, pointer up is
when we lift the finger. Use it. Create a new event. Now we need to drag the
button control object. We will use the load
level of string function. Then load the level
of selection level. Great. When we touch the
screen and the finger, we should trigger the event. Right. Click anywhere on
the screen. It works. Now, let's add some visual
elements to this scene to make it look better
in the safe area, Let's create a new text. Change the anchor to
the bottom middle. Place it like this. We can change the font, expand the text area,
change the alignment. Text input should
be tapped to play. Change the font size. To make it more interesting, I wanted to create
this blinking effect. We should create a script, but I will use animation
for this text. Important, as I said, animating UI elements
is performance expensive and you should
avoid that usually. But for this, start
seeing that has very few elements and we are only in it a couple of seconds, we can get away with any
meeting one element. So let's create an animation. I will call it tap animation. Hit the record button and
animate the alpha value. Let's see the preview. It's a bit too fast. Let's set the sample size to 30. This looks fine. Let's try it. Tap on the screen. Great. We can also add the spaceship
sprite to this level. Set the position to 00, and increase the
order in a layer. Decrease the size a bit. And we're done. See you in the next lecture.
43. UI Setup: Hello everyone. In this lecture, we create UI elements
for level selection. As you can see, we built
a nice scrolling system. To start, let's make sure we open the level selection level, explained the canvas, and under the safe area,
create one button. Let's change the source image. Use the level icon sprite, set a native size. Now let's change
a text settings. The color needs to
be white, right? Any number, it doesn't matter. They will be
automatically assigned. We can increase the font size. I will change the text
area a bit great. We can change the font. This font is a bit bigger. You can maybe disabled rapping or just decrease the size a bit. This is maybe too small, I will set it to 39. We can easily write three-digit numbers
with this font size. Now, select the button. We need to add on click event. The button needs to
use button controller. And we need the load
level of string function. This button will
lead to level one. This is just a template button. Now we can create
the Scroll Area, right-click on the safe area, and create an empty game object. I will call it level base. Now, let's change
the dimensions. We are setting the
Scroll Area Boundaries. Then right-click on the level
base and create an image. I will call it a
viewport background. Stretch it. For
the source image, use the large panel sprite. Make sure that the
image type is sliced. I will just change the color. Now, right-click on the viewport and create an empty game object. Call it a grid content. Set Anchor Presets
to the top middle. Now let's add the grid
layout group component. This component will arrange
buttons into a grid. We need one more component is called contents size filter. It will expand the dimensions of this object is we add buttons, set horizontal and vertical
fit to preferred size. Let's drag the button
under the grid content. Now, we can duplicate
the button. And you can notice that because of the grid
layout component, they are arranged integrate. Let's change some settings. Cell size can be 200. We can set a fixed
column number. Let's use three. We can add spacing between buttons and some padding
at the top and bottom. Also, let's set the alignment
to the upper center. As you can see, we can easily
create a grid of buttons. Let's add more buttons. Notice one problem. The buttons are visible
outside of the background. We have an easy fix. Select the viewport background, then add direct mask
to the component. This looks better. We just need to
adjust the padding. Notice how buttons
overlay the edge. Set bottom and top
padding to 15. Great. Finally, we can select the level base object and add the scroll erect
component or the content. Let's use the grid content. We can disable scrolling in
the horizontal direction. We only need vertical. For the viewport, use the
viewport background object. Let's try it. It looks nice. We can scroll up and down. Of course, you can change the settings and behavior
of the scrolling. I like to set this
deceleration rate to zero. Now we have UI setup for
the level selection. In the next lecture we add the functionality
and level unlocking. See you there.
44. Level Selection and Unlocking: Hello everyone. In this lecture, we create a fully functional level
selection and unlocking system. When the player wins
the first level, the second will
unlock and so on. We need to go to the end
game manager script. As you can see I mentioned before that in the
video game function, we need to unlock
the next level. But first, let's
create one variable. This will be a public
String level unlock. We don't want to ever
change this string, so let's hide it
in the inspector. This string will
be used as a key for saving and loading data. When we pass a level, we need to get the index
number of the next one. So let's create an integer
next level variable. The value will be
the current level of build index increased by one. Then we check if that
next level index is greater than the value we
store in the level unlock key. Set the default value to zero. If that is true, then we save the
next level index to the level unlock key. The key, we'll have the
highest unlocked level index. That is all we need to
code in the game manager. In Unity, create a
new C-sharp script. I will call it button icons. The script to that level
base object and open it. We need to use the UI namespace. Then let's create
some variables. We need an array of buttons. Then we need to
sprites for buttons, one for unlocked and
one for Locked buttons. We also need the number of
the first level built index. What is that number? If you take a look at
the build settings, you can see that
the first level in our case starts with
the built index two. Okay, Now we need
the awake function. It's called only once
before the start function. First, we need to get an index of the list
unlocked level. So unlocked level
will get a value from the string key we made
in the end game manager. It's important to set the default value to the
first level built index. Then let's create a for loop to go through
the array of buttons. For every button, we
check if the I plus the first level index is less or equal to the unlocked
level variable. I starts from zero. So we need to add that
first level index value. Remember that unlocked
level variable is the index of the
highest unlocked level. That means that every level with a lower index needs
to be unlocked. So first, we set the button with the index I to interactable, then set the sprite of the
baton to unlocked icon. Now we need access to the text. We need to include
the pro namespace. Create a text variable, then use the button and get a component in
children function. Remember that the text is a
child object of the button. Then we need to set
the text value. After that, just makes sure
that the text is enabled. In other cases,
levels are locked. So we need to set the button interactable variable to false. Set the sprite to
the locked icon. Also, we need to disable
the text component. That is all we need to code. Go to unity, assigned, unlocked and locked icons. Let's double-check the
first level, build index. The index of the
first level is two. Then add buttons to the array. At this point, every button
will lead to level one. We need to select buttons
one-by-one and change values. This button will lead to
a level to the next one, to level three and so on. This is the only thing
we need to do manually. It's a five to ten minute job, depending on the
number of buttons. There are ways to do this
automatically with scripts, but that is beyond the
scope of this course. For now, you don't need
to change all buttons. We only need buttons for two
or three layers for testing. Before we test it, let's go to the first level. Here we need to
adjust some buttons. The home button on the vein, and the lowest screens needs to lead to the level selection. Now we can test it. We start the game. Go to the level selection. Since this is the
first time we play, only the first level is
unlocked and others are locked. Let's try to pass
the personal level. Now, we can see that the
level two has been unlocked. Great. In the next lecture, I will show you how to
easily create new levels. Then you can connect
all battles with created levels. See you there.
45. How to easily create levels: Hello everyone. In this lecture, I will show you how to
easily create new levels. We can delete the level two. It's an old copy. For now, we have all that
we need in a level one, you can see all
managers, controllers, and other prefabs in this level. Now duplicate this scene and
call it a template string. Open it. This scene contains all
the necessary objects to create a basic
functional level. Now, we can duplicate
that template seen. This can be level two. Open it. Now it's easy to add or
remove prefabs, e.g. we can delete the meters
partner in this level. We can also change numbers, e.g. this Pound time. If you need different enemies, you can replace prefabs. Select the win condition, and update this array. We don't have meters partners, so delete the empty field. We can also change
the wind timer. Now we have a completely
different level. Let's create a level three. Duplicate that template
is seen. In this level. You can set variables
to different values. This is just an example. So I will set them
randomly with no testing. Of course, if you have some other Spanner Prefabs or anything else for this level, you can just drag
them into this thing. Just make sure that you
update the build settings. And that is how you can
easily create a levels. For testing. Just create
two or three levels. Don't create too much because
we will need to update the template seen with the new content
later in the course. I just wanted to show
you the process, but it needs to be
done when you have all things connected
between objects. Later, we create
EDS and Power Apps that needs to be
connected to the player. Keep that in mind and see
you in the next lecture.
46. Android Phone Build for Testing: Hi everyone. In this lecture, for testing purposes,
we will build the game on our Android device. We have enough content
to try the game and see how it feels
on a mobile device. Before we start, make
sure that you have the Android module installed for the Unity version you use. Then go to Build Settings and make sure you use
the Android platform. We did all of that at
the start of the course, but I just wanted to repeat it in case you missed something. Now, go to player settings. Here you can find some options like company and game name, version and icons for testing. We don't need to change them, maybe just the company name. Let's go to the resolution
and presentation. By default, outer rotation is selected with all orientations. Let's limit this
to portrait mode. Then go to other settings. For the publishing version, we will need to
change more settings. But for testing,
let's just disable this bundle identifier override. And for the target API level, choose the one with
the highest number. Now, we need to connect our
mobile device to our PC. On a mobile device, we need to enable debug
mode, go to settings. The next procedure can be
a bit different for you. It depends on the device, but usually we need
to find about phone. Then open the
software information. Now, type a few times
on the build number. You should see a pop-up
that developer mode has been turned on. Now, go back to settings. Scroll down and you should
see developer option. Make sure that it's on. Then find USB debugging, enable it, and
that should be it. In Unity, you can press Refresh and you should
see your device. If you don't see it
reconnected and make sure that you have file sharing
via USB turned on. Then we can press, build and run, create a
new folder for the build. The file name will
be Space Shooter. Click Save, and wait a few
moments when you do it, the first time, it
takes a bit longer. Bill should appear on your PC
and on your mobile device. Also, it should automatically start the game on
your mobile device. Now you can taste the game
and get a better feeling. As you can see, everything
works just as it should. Nice. Also, when you make
some changes in Unity and you want to
test the updated version, then enable development, built, and hit pitch and run. Great. Now you know how to test your
game on a mobile device. See you in the next lecture.
47. iOS Phone Build for Testing: Hi everyone. In this lecture, for testing purposes,
we will build the game on our iOS device. We have enough content
to try the game and see how it feels
on a mobile device. Notice that I'm using Windows, but to build the game on iOS, we will need a mic computer
later in the process. Before we start, make
sure that you have the iOS module installed for
the Unity version you use. Then go to Build Settings and make sure you use
the iOS platform. Now go to player settings. Here, you can find some
options like company in game name aversion and
icons for testing. We don't need to change them, maybe just the company name and remove spaces from
the product name. Let's go to the resolution
and presentation. By default, outer rotation is selected with all orientations. Let's limit this
to portrait mode, then go to other settings. The publishing version, we will need to change more settings. But for testing, let's just disable this bundle
identifier override. Go back to Build Settings. Now we need to create a build, create a new folder, and then start the process. It may take some time to finish. Here is the folder
with all data. Now, we need to transfer this
folder to make computer. Let me just switch to make. As you can see here, I have the Build folder on Mac. Inside the folder, you should
find the Xcode project. If you don't have the
Xcode application, just go to the App Store, search for Xcode and install it. It's completely free, but
it's only available on mic. Open the Xcode project. Select the unity iPhone, and you will see some settings. Most of them will be from Unity. If something is missing, you can quickly edit. Again. This is just for a test build, so you don't need
to go into details. The important part is to
go to the signing section. Here, we need to enable
automatic signing. Now we need to add a team
account which can be just you. To create it, go to Xcode, preferences accounts, and
click on the plus button. Use your Apple ID to sign in. After that, you need to add
a development certificate. Go to Manage Certificates. Click on the plus button and add the APL development
certificate. Go back to the signing section. Now we can choose a team
account that we made. Now, you need to
connect your iPhone to your Mac. On your phone. Go to Settings, find
privacy and security. At the bottom, you should
see developer mode. Sometimes to see this option, the Xcode must be open, otherwise you will not see it. Let's enable developer mode. Your phone will restart. After death on Mac. Make sure you
select your iPhone. To start building the game. Click on the play button. This will take some time. If you get some
error tried to open your Unity project on Windows
with a different version. Actually, I got some
weird error that I couldn't resolve with
all possible fixes. It turns out it's because
of the Unity 22 version. Something is wrong. I'm sure they will
fix it in the future. Maybe you will not have errors
with the latest version. But I needed to open my project on Windows in Unity 21 version, build it and transfer files on Mac and repeat this
whole process, then everything was
fine with no errors. If you get this pop-up message, just type the password
you use to sign into your Mac and click
on always allow. When the build is finished, you will see this message. The game couldn't open on your iPhone because we need
to trust the developer. On the phone. Go to Settings. General device management. Here you will see that
developer app open it, then you need to
trust the developer. Now you can find the
game and test it. Let's play it a bit to
see if everything works. Nice, It's all good. This is how you test your
game on your iPhone. Have a nice day and see
you in the next lecture.
48. Scriptable Object Spawner: Hello everyone. In this lecture, we create a scriptable
objects that will help us spam Power Apps. Script double object is a data container independent
of class instances, something like an asset. They are very useful for
memory saving because they are really small,
lightweight, and optimized. Let's see how we can create
a scriptable objects. First, let's create a folder. Then create a script. I will call it scriptable
objects example, and open it. Delete all functions. And instead of mono behavior, let's inherit from the
scriptable object. This scriptable
objects will hold a reference to the
Power App prefabs. So let's create an
array of game objects. Next, let's create a function that was found one
of the Power Apps. It needs to be public
and it takes one vector, three parameter for
this pound position. Let's get a random index. Then we can use the
Instantiate function. Spam, the power up with
that random index. Use spawn position and rotation. To create a script of
an object as an asset, we need to use the create
Asset menu attribute. Then we can use a menu name which will be
scriptable objects. Power Apps Partner. I will show you what this
menu name in a second. First, let's add a default name to the object we will create. I will call it spawner. It doesn't matter. We will change it anyways. Go to unity. Right-click, go to Create. And now you should see scriptable objects
power up spammer, that is the menu name we chose. So let's create one
Power Apps Partner. As you can see, the
default name is Spawner. I will change it to power
up spamming or basic. Now you should see the array of Power Apps in the inspector. Here, we will add the Prefabs
that we need to pound. Notice how it's easy to create another scriptable objects that can have different prefabs. We need just one. So delete this one. Let's add some
randomness to spouting. First, we need one
integer span threshold. Then in the function we can
get a random number 0-99. Remember, the last
number is not included. After death. We check if the random chance number is
greater than this threshold. If that is true, then we need to
instantiate a Power App. Let's go to unity. We can set this bound
threshold to 80. So when we get a higher number, then we will span one
of the Power Apps. The chances around 20 per cent, precisely in 19%, since
the maximum number is 99. So when Power Apps, my idea is to spout them when the player
destroys meteors, but you can also
easily found them if a certain enemy is destroyed. And let's say the meter version, go to the meteor script. In the death sequence, we need to call a function
that will expand Power Apps. But first, we need a script
of an object variable. I will call it power
up as founder. It's a good idea to check that this parameter is not null. Then we can call the function from the scriptable objects. The function pays the
position of the meteor. That's all we need to code. In Unity. Select meteor prefabs. We need to set up a reference
for the scriptable objects. Drag the scriptable
objects to the empty failed to taste sparkling. We can select the
scriptable objects and drag any prefab
into the array. I will use the
grid enemy prefab. I will also modify this level, one pound more meteors. Just delete the enemy spanner, then decrease spawn time
to get more meteors. Course, we need to select the win condition and modify
the size of the array. Let's try it. When we destroy it, a meteor, the enemy can expound. Great. In the next two lectures, we create power-ups for the scriptable objects
pounder. See you there.
49. Health Power Up: Hi everyone. Let's see how we can create
collectibles and Power Apps. In this lecture, we create a Power App that will
heal the player. First, we need a
Power App, sprite. Use the yellow one. Increase the sort order to four. Now let's add some
components. Rigid body 2D. We don't need to
change any option. We actually want
gravity in this case. Now, let's add the
box collider 2D. It needs to be a trigger. Then we can adjust the
size of the collider. This looks good. Let's create a layer
for collectibles. We need to change the
collision matrix. The collectibles layer needs to collide just with the player. Now, we can create a
new folder and script. I will call it power up here. Add the script to the object. Let's open it. First. We need an integer
variable here, amount. Then we can use the On Trigger
Enter to the function. Because of their layer metrics, I know that this object will collide just the
way to the player, but maybe you will need this power up to collide
with more objects. Then we can check if the
object has the tag player. Here, we will heal the player. We need to create a function
in the player stats script. Let's open it. In the player states, create a new public function. Call it add health. It takes one int parameter. Here we increase the health
variable width, heel amount. Then check if the current health is greater than the
maximum health. If that is true, let's set the health
to the maximum value. In this way, we can't have more healthy than
the maximum value. We also need to update
the Health Bar. Let's go back to the
Power App Script. Here, we need to get the player stats component
from the collision. Then call the Add
Health function. After death destroyed
the powerup object. This is all we need to code. Go back to Unity. Let's sit heel amount. Then create a prefab. We can delete one
from the scene. Now go to the scriptable objects that we made in the
previous lecture. This green enemy was
just for testing. Let's replace it with
the heel prefab we made. Then just make sure that meteors use the
scriptable objects. We did that in the
previous lecture, but just in case
you miss something, we can try it now. Let's damage the player, then destroy meters and
the Power App should span. Great, everything works. See you in the next lecture.
50. Shield Power Up: Hello everyone. In this lecture, we create a shield Power App that will
protect the player. First, let's use
a shield sprite. Change the name, and
order in the layer 25. Notice one strange thing. The spreadsheet is looking
blocky and really bad. This sprite has some gradient and it causes this
rendering issue. To fix it, Let's select
the shield sprite. We need to override some
settings for Android and iOS. Enable override for iOS. Then change the format to this. Apply changes and you
will see improvement. It looks much better. Now select Android Settings
and do the same thing. Don't forget to
change the format. I will put a link to the list
of supported formats and settings so you can find the
best options for your game. Now, let's drag the shield
under the player prefab. Adjust the position a bit. Then we need to add
polygon collider 2D. It needs to be a trigger. We can also edit
the collider called Control and click on the
lines to erase some vertices, fewer vertices,
better performance. This is fine. You can spend more time
on this if you wish. Let's create a new
layer for the shield. Call it shield. We need to go to the
collision matrix. The shield needs to
collide only with enemies and enemy projectiles. Then we can create a new script. I will call it shield. The script to the shield
object and open it. Let's delete the
default functions. The shield will not have held, it will just count hits to create a hits
to destroy variable, I will set the value to three. We need one public bool
variable protection. When we enable the shield, makes sure that we
have three hits to destroy and that
protection is true. Now, create a function that
will damage the shield. We decrease hits to
destroy it by one. Then check if hits are
less or equal to zero. Then set protection to false
and deactivate the shield. We can also pick
up shield power up while we already have a shield. Then let's just
repair the shield. Set hits to destroy it
to the default value. Now we need the own Trigger
Enter to the function. We know that the shale
to collides Just a bit, enemies and enemy projectiles. So we can try to get
the enemy component. This line of code will
try to get the components from the collision and
store it in this variable. Then we need to
destroy the enemy. We can use an insane amount of damage to make
sure we destroyed. Then damage the shield. The shield collided
with projectile, then destroyed the projectile
and damage the shield. Then go to the
player stats script. Here, we need a
reference to the shield. Then we need to prevent the image while the
shield is active. So in the tech damage function, if the shield
protection is true, then return and don't
execute the code below. Unity to taste it, Let's turn on protection. Then select the player and set up a reference or the shield. Let's try it. We have a shield
that should protect us from three hits. 123. Great. Just a small digression to make sure that the bullets are visible
in front of the shield, we can increase sort order. Now let's create another script. I will call it player
shield activator. Select the player
and add the script, open it and delete
default functions. We need a reference
to the shield. Then let's create a public
activate shield of function. This function will be called
when we pick up a power-up. Then we check if the
ship is already active. If not, let's activate it. If it's active,
repair the shield. Go back to Unity. Drag the shield into
the empty field. Now select the shield
and disabled protection. Also disabled the shelf object. Select the player
and apply overrides. Now, we need to actually
create a PowerApp object. Go to the Prefabs folder and drag the hill power
up into the scene. We will create another prefab
by adjusting this one. In that way, we are saving time. First, let's change the sprite. Then we can remove the
script and change the name. Now, we can create a new prefab. The last thing we need to do
is to create a new script. Call it power up, shield. Select the powerup
and add the script. Open it. We need the On Trigger
Enter to the function. First, we make sure that the collision happened
with the player. Collision. We need to get
to the shield activator. Then call the activate
shield function, and then destroy the
PowerApp object. Save it, and go to Unity. Don't forget to
override the changes. We can delete the
prefab from the scene, then go to the
scriptable objects. We need to add a new
prefab to the array. Choose the shield prefab. Let's try it. We need to get a
shield power-up. Now, we're protected
for three hits. Great. In the next lecture, we create UI icons so we
can see the shield status. See you there.
51. Shield UI: Hi everyone. In this lecture, we create UI for the
shell to power up. The UI will show the
status of the shield. Let's expand Canvas and
right-click on the safe area. We need to create an image. I will call it shield base icon. Let's change the source image. Use the icon base sprite. We can change the color. Then create another image. It needs to be a child object
of the shield base icon. This will be shield icon. Change the sprite. Click on the Set
native size button. Let's zoom out. Select the base icon
object and change the Anchor Preset to
the upper left corner. Now, we can change the position. It needs to be below
the Health Bar. Maybe the base is a bit too big, so let's change the
width and height. This looks good. Now we can duplicate it. Move the duplicate to the right, then repeat the process. We needed three icons because the shield protection
is three hits. Now select all based
icons and disable them. Select the canvas prefab. In overrides, select shield icon and click on the Apply
select that button. Now, in every level, this prefab will
have Shield icons. The next step is to go
to the shield script. Here we need an array
of game objects. I will call it shield base. This will be a reference
to the shield icons. When we enable the shield, we can use the for loop
to enable all icons. Then we needed to create
a function that will update icons when the
shield takes the image. So let's create the
update UI function. We will use the switch function. We check the hits to
destroy variable. In case zero, that means that the hits to destroy
variable is zero. Then we need to
disable all icons. At the end of the case, we use break to exit
the switch function. In case one, we need to enable the first icon and
disable the others. In case two, we
enabled to icons. In case three, we enable all icons in the
damaged function. Let's make sure that
the hits to destroy variable is zero when
the shield is destroyed. Also in this function,
we update UI. We also needed to update you
are in the repair function. Let's do one more thing. In this speech function, we can have a default case. This will happen when the variable we are
checking and that is hits to destroy has a
different value than any case. We don't have any other
cases than 012.3, but we can put a debug log. So if that happens,
something is wrong. Let's go back to Unity. We need to drag the
icons into the array. Let's try it. We need shield power-up. Now, let's them as
a shield so that we can see if the
icons will update. As you can see it works. We are not done. This is important. You need to update references in the template sin and other levels that we
made for testing. Notice that if we use override for the player and
go to another level, we don't have references. The prefabs can't remember references to other
Prefabs or objects. I repeat at the
end of the course, we will finish the temporary
scene and then you can just duplicate it
to create a levels. After you updated your levels, Let's go to the next lecture.
52. Shooting Power Up: Hi everyone. In this lecture, we create a shooting Power App. As we pick it up, we get more shooting points. And when we take the image, we lose shooting points. First, let's create
shooting points. Select the one that we already
have and change the icon. Now, we can duplicate
it and rename it. Then adjust the position, duplicate it again
and change position. We need one more. This point will
have some rotation. So change the name. Now, let's duplicate points and place them on the right
side of the spaceship. Remove the minus sign from the x value to make
them symmetrical. For the last one, we also need to
change a rotation. Now, let's go to the
player shooting script. Let's make some changes
and organized the script. I will just move
this shooting point below the shooting interval. Then we can add a
header attribute. Then let's create a header
for upgrade points. Now we need references to
four transform points. Then let's create a header
for the last two points. With rotation, we need
to transform points. Then we need one integer
variable upgrade level. Now, we need to modify
the shoot function. I will comment this
line for a second. We will use the switch function. It will check the
upgrade level variable. In case zero, we should
only from one point. In case one, we should affirm
two points, left and right. Change the basic should point to the left, cannot position. Then duplicate it and set
the right cannon positioned. In case two, we shoot
from three points from basic left and
right shooting points. In case three, we should
affirm five shooting points. Use the second arrived Canaan and a second right
cannon positions. In case four, we showed
from all shooting points, including the points
with rotation. It's important to use
the rotation from the points instead of
quaternion identity. We can also add
the default case, which will do nothing a
debug log if you wish. Notice that we use the
Instantiate function a lot, creating and destroying
a lot of objects. In this case, bullets
can sometimes affect performance
on mobile devices. So at the end of the course, see the optimization section
and how we upgrade this. The next step is to create a public function that will increase the upgrade
level variable. After we increase the level, we need to check if
it's greater than four, which is our maximum. Then just set it to four. Go to Unity, connect or shooting
points with the script. Then we can apply
overrides to the prefab. Now, let's create a PowerApp. Use the health power-up prefab. We will adjust it and
create a new one. Change the name, sprite, and remove the script. And let's create a new script. I will call it
power up shooting. The script to the prefab. Use the On Trigger, Enter to the function. Check if the collision
happened with the player. Then we need to get the player shooting component called the increase
upgrade function. I will hard-coded to
increase the upgrade by one, but you can create a variable and paste it here. If you want. Then destroy the Power App. Let's go back to Unity. Create a PowerApp prefab, delete one from the scene. Then we need to find our scriptable objects at
the prefab to the array. To make it easier to test, we can always bound this
Power App. Let's try it. As you can see, it works. Let's make the player loses
one upgraded level when he takes damage in the
player shooting script, create the decrease
upgrade function. Decrease the level by one. And also make sure that
it can go below zero. Go to the player stats script. We need a reference to the
player shooting script. In the start, use
the Get Component. Then when the player
takes the image, let's call the decrease
upgrade function. This is all we need to code. Let's try pick up a Power App, then take damage and the
upgrade level should decrease. Nice to have a nice day and
see you in the next lecture.
53. Power Ups Update: Hello everyone. Let's quickly update
Power Apps Scripts. There is a case when a player doesn't pick up the Power Apps, those power-ups would
fall into infinity. So we need to use owned
became invisible. This is the same function
we use for bullets and meteors and everything that
can go off the screen. Here, we need to destroy
the Power App GameObject, copy this code in every
Power Apps Script. And that's it. Thanks for watching and see you
in the next lecture.
54. Boss Concept and Preparations: Hello everyone. Let's
see the concept that we will apply to
create the enemy boss. The idea is to create states. Each state will be responsible
for one type of behavior. E.g. the interstate
will be responsible, have the enemy boss will appear. Then we can have
a shooting state, a special ed tech
state, and so on. The state's, there'll be child
crisis of base state guys. Every state inherit the
run state function, which will contain
logic for that state. We will also have a
boss controller script. The controller will have the change state
function that will be responsible for
changing states. E.g. after we run some
state and it's finished, we call the change state
function to change the state. This is the logic we will use. Of course, we will spend the boss at the
end of our level. Now, let's create
our boss GameObject. Go to the enemy sprites, use the big purple one, change the order in layer, then change the name. Let's add some components. We need a rigid
body 2D component. Make it kinematic. Then let's add a
box collider 2D. Click on the Edit button
and adjust the size. We will need one more collider. Also adjust the size. Exit edit mode, then add
composite collider 2D. The box collider there is
need to be used by composite. Also, let's enable
Is Trigger option. We need to change the layer, select enemy to
prevent some errors. For now, we need to
disable colliders. Now that we have basic stuff
done in the next lecture, we will create a base state
and both controller scripts. See you there.
55. Boss States and Controller: Hello everyone. In this lecture, we create a foundation for
the state system and controller to stay
organized in scripts. Let's create a
purple box folder. Now we can create two scripts. The first one will
be both base state, and the second will
be both controller. The scripts to purple boss. I will just move them up in the inspector Open base state. Here, we can delete
the update function. Now we need variables
and kMer boundaries. But instead of writing them, I can go to player
controls and copy them. We don't need this
offset variable. This is a base class. So child classes will maybe
need one of these variables. That's why we need to change access modifiers to protect it. In the awake function, set Main came to
our main camera. Let's go to player controls. Scroll down and copy this part. When we define variables, place them in start. We can change numbers a bit
because the bus is a bit bigger and he needs to be in the upper half of the screen. Also, start needs to be a
protected virtual function. Then let's create a public
virtual run state function. Leave it empty, then
create another public. We're stopped state function. Or the both states, we will use coroutines
and this stop state function values
Stop Paul curtains. Now let's go to bus controller. We don't need the
update function. Outside of the class. Let's create enums. We will use enums to
identify both states. So public enum, both state. And now we write the
states that we will have. We need an interstate
when the boss appears. We need n at texted
that I call fire. We need a special attack state. And that state, you can add
as many states as you want. Then let's create a public
change a state function. It will take both
state as a parameter. We will use this function
to change states. Let's use the switch
function to check the state. If the state is enter,
then there's something. We can copy this
part of the code and paste it for
every state we have. Now, just check
different states. Great, We have enough to
start creating states. In the next lecture, we create the interstate.
See you there.
56. Enter State: Hello everyone. In this lecture, we create
the state enter for the boss. The interstate will define
have the bus will appear. And my idea is to make him go to a certain
point on the screen. Then change the state. Let's create a new script. I will call it both. Enter the script to
the boss and open it. First. Instead of
modern behavior, let's inherit from
both base state. Remember in the parent class, we have two virtual functions
that we can override. Also, we can override
the start function. Let's create a
vector two variable, call it enter point. To this vector, we will assign a position and the bus
will fly to that position. Next, we need a speed variable. Let's override the
start function. We can use Bayes start to define variables for
screen boundaries. Then we need to choose a point where the
both Seville appear. I will go with 0.5 on the
x and 0.7 on the y-axis. We can delete the
update function. As I said, we value square root functions to
define state behaviors. The eye enumerator run
interstate function. Then we use the while loop. So while the distance
between the boss and enter point is greater than
a really small number. We need to move the bus to that point using the
move towards function. First, we write the
position of the bus, then the position
we need to reach. And then we choose
the speed that is multiplied by Time.deltaTime. Then we wait for
the end of a frame. We repeat this until we
satisfy this condition. After we exit the while loop, we need to change the state. So let's go to the parent class. Both base state. Create a protected
both controller variable in the awake function. And let's get the component. Remember, in the bus
controller script, we have the change state
function that we're looking for. In the bus enter script. We can use the controller and call the change state function. After the interstate, we
go to the fire state. Now we need to call this function override
the random state. Here, you start correcting. Let's override the stop state. We can just use
the base function. To remember you, that function
will stop the keratin. Now, go to both controller. Create a reference for
the bus interstate. In the switch function. When we are in the interstate, we use run state to test states. Let's create one
ball variable test. And the enum test state. In the start. If
the test is true, then we change to
the test state. Let's go to unity. Drag the boss enter script
into the empty field. Here you can choose the state. Of course, we need Enter. Let's move the boss
outside of the screen. When we start the game, the boss should go
to our entry point. Of course, don't forget
to set the speed. As you can see, the
bus will appear. If we exit play mode, we can see debug message. Let's double-click it. You can see that it's
a debug from line 33. That is the fire state. And if you remember, at the end of our interstate, we change the state to fire. So everything works. In the next lecture, Let's create the fire state.
57. Testing States: Hello everyone. This is a quick lecture that I
decided to place here. I wanted to show you
how to properly test states and discuss both
movement restrictions. Before we start, you can remove the boss base state script from the boss if you didn't yet. This is a base class and it doesn't need to
be on the object. Just a silly mistake. It won't break anything, just it's not needed. Let's open the boss
base state script. As you can see in the
virtual start function, we get movement restrictions. This will work fine
because we usually respond the bus at
the end of a level. However, when testing, we
spun it at the beginning and those restrictions are not set correctly because
of sin a machine. If you remember, in
player controls, we use a curtain to set
boundaries for the player. You can see that
we wait a bit of time before setting
restrictions. I explained why we do that in the camera boundaries lecture
because of cinema machine. So if we go to both enter, you can see that they use the base Start function
to set restrictions. Remember that this class is a child class of
both space state. So if we span the boss
at the start of a level, we can get the wrong
boundaries that all being said to properly test the bus with correctly
set the boundaries, we must do the following. Make sure that the
test variable is true and choose the taste state. Then disabled the boss object. Go to the simulator. I chose play in window, start the game, and
then enable the boss. In this way, the
movement restrictions for the bus are correctly set. Remember, this is all
just for testing in a real game with pound the
bus at the end of a level. So we don't have that problem. And that's it for this lecture. Thanks for watching
and see you soon.
58. Boss Fire: Hi everyone. In this lecture, we create a shooting
state for the bus. As you can see, the bus will
start shooting after he ends the interstate that we
made in the previous lecture. First, let's create
shooting points. They need to be a child
objects of the boss. We need for shooting points, placed them in front
of the canons. Next, let's create a new script. Call it both, fire the script to the boss and open it. This class needs to be a child
class of both base state. We can delete the
default functions. Then we need some variables. We need a float variable speed. Then float, shoot the rate. We need one game object
variable for the bullet prefab. To organize the script,
let's use header. Now we need a transform array
to store shooting points. We can create the eye enumerator function around a fire state. We need a float,
shoot the timer, a float fire state timer, and a float fire
state exit time. And that will get
a random value, 5-10 s. I think that it's a good idea to randomize the duration
of this fire state. Then let's use vector
to target position. The bus will need to
move to that position, which was it randomly between
our maximum boundaries. Let's use a while loop. While fire state timer is less or equal to fire
state exit time. The boss needs to move to the target position
and shoot bullets. If the distance
between the boss and the target position is greater than a
really small number. Then continue to move. Else. That means we reached
the target point. Then we choose another
position, again, which was it randomly between
our maximum boundaries. Remember, we define these
variables in the base class. Of course, while
the bus is moving, he needs to shoot bullets. Let's increase should
timer by Time.deltaTime. If should timer is greater
or equal to shoot rate. Then we shoot from
shooting points. Use a for loop to go
through all points. Then reset should timer. Then we wait for
the end of a frame. Then increase buyer state
dimer by Time.deltaTime. After enough time, we
will exit the while loop. Now, let's override the
run state function. Use start coroutine
to start fire state. Then override the stop state
and use the base function. Just like before. Let's go to the bus
controller script. Create a reference
to the both fire. In this speech function
under the fire case, use the bus fire that
around a state function. Go to Unity. Let's set the speed. Then, set the
shooting rate to one, which means every second
or the bullet prefab, we can use the same that
we use for purple enemies. Next, let's drag the shooting
points that we made. The last thing, drag
the boast fire script. We can leave the interstate
as the test state, since at the end of it, the boss should change the
state to fire. Let's try it. We see the interstate and
switch to the fire state. Notice that after the fire
state finish the bus stops, we need to repeat the fire state or change it to some
other state, e.g. the special ethic state. Go back to the boss fire script. In the eye enumerator function. Outside of the while loop, we call the change
state function. Change it to the spatial state. If you like, you can
add some randomness. We can get a random number. This can be zero or one. If the number is equal to zero, then repeat the fire state. Otherwise, change
it too special. For easier testing, I will always change it to
the special state. And that's it. In the next lecture, we create the special attack
state. See you there.
59. Special Attack: Hi everyone. Let's create a
special ed tech for the boss. The boss will fire one big slow projectile
that can damage the player. The projectile will also
burst after some time and send smaller projectiles
in a circular direction. First, let's create
another child game object. I will call it a special point, because from that point, the bus will shoot
a spatial attack. Let's move it in front
of the main Canaan. Then let's create a new script. This will be both spatial. Add the script to the
boss and open it. We need to inherit from
the boss base state class. Then let's create variables. We need a float speed variable. Then a float wait time. This variable will
determine how long the bus will wait after
the special attack. Then we did one gameObject
especial bullet. Of course, we need
a shooting point. Then we need a vector to target point for
the first position. Let's override the
start function. We don't need to use
the base function. Just set the target point. If we use a viewport to
world point to determine from which point the boss will
fire the Special Ed Tech. I will go with 0.5
on x and 0.9 on why. You can maybe go a bit lower. Now, let's create the eye enumerator run spatial
state function. First, the bus needs to
move to the target point. We use a while loop and check the distance between the boss
and the target position. While the distance is
greater than 0.01, we need to move the boss. We use the move towards
function just like before. Then we wait for the end of a frame outside of
the while loop, which means that the boss
is at the target position. We instantiate a special bullet. Then we wait a bit and then change the state to fire. Now, we need to override the run state and
stop state functions. Use start carotid. Go to the bus controller script. Here we need a reference
to the boss special. Then in the change
state function, use the bus spatial run state. Go to Unity. And let's set variables. Speed. It can be too. We can wait for 5 s. We don't have the
spatial bullet prefab yet, but we can connect the shooting point
that we made earlier. Now, let's create a
special bullet prefab. Go to enemy sprites. Use the big bullet sprite. Change the name, or
they're in a layer. Then set the collision
layer to enemy projectiles. We can make it a bit smaller. This is good. Add a rigid body 2D
component, make it kinematic. Then we need a
circle collider 2D. It needs to be a trigger. We can adjust the size, decrease the radius a bit. As I said, this
bullet will burst and many bullets in a
circular direction. E.g. I want to spend
six minute bullets, so I will divide 360 by six. The result is 60. Remember it? And then let's create a child object of
the spatial bullet. I will call it spawn point. The idea is to change the
rotation on the z axis. Let's duplicate
this pound point. Change the rotation to 60, then duplicate it again and
increase the rotation by 60. That means it will
be one-twenty. Repeat the process until
the last span point, the rotation has a value of 300. You should have six points. Notice how the green axis
changes as we change rotation. This is important. Now, let's create a new script. Spatial bullet. Add the script to the
object and open it. First, we need some variables. We need a float, damage, speed and rotate speed because
this bullet will rotate. We also need a rigid
body 2D reference. We also need a reference to
the minute bullet prefab. The last thing, we need
an array of points. In the start, Let's set the velocity to vector
two down multiplied by speed in the update function. And let's rotate the bullet
with transform that rotate. Rotate the bullet on z-axis. Use Rotate speed multiplied
with Time.deltaTime. Then let's create the eye
enumerator explode function. Here, we need to destroy the spatial bullet and
instantiate many bullets. First, let's set the
random explode time. Then we wait that random time. Use a for loop to go
through all expound points. We instantiate a minute bullet
on spawn point position. And now this is important. We use the rotation
of this bound point. Then we destroy the
spatial bullet object. In the start function, we call the explode function
with start coroutine. Of course, this bullet also
can damage the player. So let's create
their own Trigger. Enter to the function. We check for the tech player, then damage the player. After that destroyed the bullet. In this case, we don't
respond minute bullets. Just as before. Let's use on became invisible. Go back to Unity. Set the damage. Speed needs to be yellow. Then set, Rotate speed. Drag the rigid body 2D. We don't have many bullets yet, but we can drag expound
points into the array. To speed up the process
of creating many bullets, we can use the purple
bullet prefab. This is the one we use
for purple enemies. Change the name,
remove the script, then create a new one. Call it mini bullet. The script to the
mini bullet object. And open it again to
speed up the process, let's copy the code from
the purple bullet script. If you don't have it open, you can find it through
Solution Explorer. Let's copy the whole script. We will make two changes. Paste it. First, I will just add serialized field and remove
the gate component part. Then the important part, replace vector two down
with transform that up. If you look at the description, this is the green axis
of the transform. Remember, when we
rotated objects, the green x is also rotated. So the minute bullet will
move in that direction. Go back to Unity. Let's set the damage and speed. Don't forget the rigid body. Now create a new prefab. Delete one from the scene. Select the spatial bullet. Drag the mini bullet prefab. Now let's create a
special bullet prefab. Delete one from the scene. Select the boss. Drag the spatial bullet prefab, and drag the both spatial
state into the empty field. Let's test it. I will start the test
from the interstate. We can see the interstate, then the fire state. And we should see
the spatial state. Then after waiting some time, the bus goes to the fire state. Again. Very nice. Thanks for watching and see you
in the next lecture.
60. Boss Stats and Death: Hello everyone. In this lecture, we find out how to damage
and destroy the bus. Before we start
to code anything, let's quickly create animations. You know, the procedure is the
same as for other enemies. Select the bus and go to
the Animation Window, create a new animation. This will be both either
use the default sprite. Then let's create
another animation which will be both the image. Set the sample rate to 30, and use the white sprite. Note that at the
end of the lecture, we will replace this wide
sprite with something else. It will look better. Go to the Animations folder. Select both the image
and disable a loop time, open the animator
and select the boss. Create transitions. We need one trigger
parameter damage. Just like other animations, from idle to damage, disabled exit time. And use parameter. Then from damage to either use exit time with the value of one. The last thing, select both
the image and add a tag. It will be the mg. Now we
can create a new script. Call it both stats. This script will inherit
from the enemy class. Just to remind you, in the enemy class, we have a lot of variables and functions that all enemies use. Now we need a reference
to bus controller. We can delete the
default functions. Let's override heard sequence. Here, we will start
the damage animation and disabled triggering
if it's already running. We already use this
technique in the course, so I go a little bit faster. Next, we need to
override that sequence. Here, we need to
change the state to death and instantiate
the explosion prefab. I will just set a random
rotation for the explosion. Also, the player needs to take the image if he
collides with the boss, use the On Trigger
Enter to the function. This is the same
procedure as before. Go to unity, the
script to the boss. Then we need to set
some variables. This is contact damage. Use the animator
from this object. Don't forget to drag
both controller. Now let's create another script. Call it both death and open it. We need to inherit from both
base state delete functions. Now let's override run state. When the boss dies, we use End Game Manager and
start resolve sequence. Next, let's deactivate
the boss game object. Now go to both controller. When the boss is
in a dead state, then we need to stop
all other states. So use stopped state
for each state. Then as always, we need to
create a reference. Boss debt. In this case. In the switch function, use both debt run state. Let's go to unity, the bus, that
script to the boss. Now we can enable colliders
and drag boss death into the empty field. Let's try it. As you can see, we can
damage and destroy the boss. But I think that the
widespread is a bit too much. So let's change the animation. Select the boss,
go to animation, and open both the
image animation. Replace the widespread
with the default one, then hit the record button
and change the color. You can experiment and see
what will look the best. Let's try with a bit of yellow
and a lower Alpha value. Let's see how it looks. I think it's better. The explosion is a bit small, so let's create a bigger one. Use the prefab, we have. Rename it and change the size. Then create a new prefab. Select the boss and
replace the prefab. We can delete one
from the scene. Nice. The next thing we
need to solve is a collision between the
boss and the shield. At this point, the shield will instantly destroy the boss. Let's change that. Select the boss, create a new tag. I will call it boss. Use it for the bus object. Then we need to open
the shell script. As you can see, the shield will deal a lot
of damage because it's designed to instantly
destroy smaller enemies. Now, we can check
if the collision happened with an object
that has the big boss. You choose, what will happen? I will destroy the shield
instead of the boss. So set hits to destroy it to
zero and damage the shield. Then return and don't
execute the code below. But let's try it. Nice. It works. See you in the next lecture.
61. Spawn Boss: Hello everyone. In this lecture, I will show you how
to span the bus at the end of a level,
select the boss. Then we can uncheck
the test variable. Open the bus controller
script In the start function, and let's set the
state to enter. Go back to Unity and
select a win condition. Here we have the duration of the level and
references to spawners. Open the script. We need one ball
variable, his boss. In the update function,
after time expires, we will use the start resolved sequence to determine the
outcome of the level. Let's do that only if there
is no boss in the level. We check the bull variable. If has both is false, then start the sequence. Notice that we always
disabled spawners. This is the important part. Go back to Unity. This level has the boss. So let's set the
variable to true. The idea is to span the boss when the enemy
spanner is disabled. So salad enemy spanner
and open the script. Let's create a game object
variable for the Boss prefab. Let's use the own
disabled function, which is called when the object, in this case,
Spanner, is disabled. First, we check that the
Boss prefab is not null. We do this because in other levels and maybe
we will not have a boss. So this will prevent errors. But if we have it, then let's create a
vector to pound position. Makes sure that is found
outside of a screen. For the y-axis, use a
number greater than one. Then instantiate the Boss
prefab at this position. However, on disabled is
also called when we go to another level or we restarted expounding
objects while we changed, since can cause errors. To fix it, we need to
add one more condition. Go to win condition, create a public bool, can expound boss
and set false as the default value when
the timer has expired. And we have a boss in the
level that is the case, then set can span both to true. We need to know this value before spawners are deactivated. So move the if else statement up before we deactivate
the spawners. In Enemy Spawner. Create a reference
for when condition. In the non-disabled function. Check if the wind condition
can expound boss is false. Then a return and don't execute. The code below. That is all we need to code. Go back to Unity, create a purple Boss prefab. Delete one from this scene, select enemy spanner and
drag the Boss prefab. Also dragging the win
condition object. Now, I will select a win
condition for testing. Let's set the duration of
this level to 5 s. After 5 s, the spammers will deactivate
and the boss will appear. Let's try it. Survive 5 s.
And you can see the boss. Let's destroy it. Now, we should see windscreen. Great, it works. See you in the next lecture.
62. Background Sound: Hi everyone. We didn't mention
sound and music yet. So in this lecture, I will show you how to
play background music. We will not go too deep into sound settings and techniques. I will show you simple examples through this in
the next lecture. So you get a basic idea
of how sound works. First, I will import
the sound folder. You can find it
in the resources. Here we have a few sound
clips that we will use. To start, let's
organize the hierarchy, create a new game object, rename it, and reset the
transform component. Then let's create
another game object. Call it background
sound or music. Reset the transform component. Now we need to add the audio source
component to the object. Audio source has a reference to the clip we need to
play in some settings. Let's drag the
background music clip into the empty field. Make sure that play
on awake is enabled. This will ensure
that the audio clip starts playing when
the scene loads. Since this is background music, we need to enable
the loop option. I know that this
music is a bit loud, so I will decrease
the volume to 0.3. Before we try to select the main camera and make sure that it has
an audio listener. It should be there. By default. This audio listener
will listen to sounds from audio sources and play
them through speakers. Then select simulator,
change it to gain a window. Then make sure that
audio is enabled. Go back to simulator
and start the game. You should hear music as
soon as the level starts. Nice. You can download more music for different players and
repeat this process. In the next lecture, we add shooting and
explosion sound effects. See you there.
63. Shooting Sound Effect: Hello everyone. Let's create some sound effects. The first one will
be shooting sound. Select the player. Add the audio source component. Use the laser gun clip. Disable, Play on awake because we will start with this
sound through a script. I will just turn
the volume down. Then go to the player
shooting script. Create an audio
source reference. I will call it a source. Then go to the shoot function. Here we use source that play. This will play the sound effect when a player shoots
laser bullets. Go back to Unity. Drag the audio source component. Don't forget to override
the settings on the prefab. Let's try it. As you can hear it works. The next thing, Let's create
an explosion sound effect. Go to prefabs. Select the explosion. The audio source component. Use the explosion AudioClip. Makes sure that play
on awake is enabled. This effect is also too loud, so I will set the volume to 0.3. Every time they
explosion is pound, we should hear the
sound effects. Great. Now let's create a Power
App, sound effects. Here we have a
different situation. I will show you why. Let's add the audio source
to any power app Prefab. Then open the script. We need to play the sound effect when a player collects
this Power App, that would be here. But if we try to play
the sound effect using the audio source
that is owned this object, nothing will happen is because
we destroyed this object. In the next line of code
is we destroy the object. Audio source will
also be destroyed. So we need a different approach. We can create some kind of sound manager and
get around this. But we also have
one simple solution with limited options. Let's use a simple approach. Go back to Unity. We can remove this audio source. Then go back to the script. Now, we need a reference
for out there clip. I will call it a clip to play. To play the clip, we use the audio source class
instead of an instance, call audio source
with capital a, and use play clip at point. First, choose the
clip, then position. And we can also
choose the volume. This clip is a bit quiet, so I will choose
the maximum volume. Let me explain how
this will work. This audio source class, we'll create a new object with the audio source component. The new object, we'll
play the sound and it will destroy itself
after is downplaying. Save this and go to Unity. Chose the Power App clip. You can repeat the process
for other Power Apps. Then let's try it. You can hear the Power
App sound effect. If you manage to pause the game right after
you pick it up, you can see that one shot
out their game object. This object is created with the audio source component and
it plays the sound effect. As I said, this is a simple solution
with limited options. We really don't have control over these options
except the volume. So keep that in mind. If you need to use audio mixers and some advanced effects, you should go with the
sound manager options. For this project, we
use a simple approach. This is all for this lecture. See you in the next one.
64. Ads Setup: Hello everyone. Let's import
ads into our project. Before getting into details, we need to do a basic set up. Notice that I'm in
the start scene, which is our first
scene in the game. Go to Window Package Manager, make sure that Unity
Registry is selected, and search for advertisement. As you can see at the time
of recording this video, the name is
Advertisement Legacy. This is because Unity
is in the middle of transition to a new way
of add implementation. But right now the
documentation is really poor and there
are no examples. Don't worry, this package will be available for some time. Also, there will be an update to this course when the
advertisement package becomes unsupported. For now, my advice is to
use it as long as you can until we get more documentation and examples for the
new implementation. That being said, click
on the install button. Unity will ask you, do you want to use the
new or legacy package? Let's use the legacy package. Now we need to link
our Unity project to a project ID from
Unity Services. You can click on the
link that leads to the Unity dashboard or just
Google Unity dashboard. You will need to sign
in with your Unity ID. We will continue
this in a moment. For now, let's go back to Unity, go to Project Settings,
Select Services. Then we need to choose
an organization. If you don't have it, probably you will have a
button to create it. Or when you sign into
your Unity account, find organizations
and you will have a button to create
a new one in Unity. Select your organization. My will be game
test development, and create a project ID. We can say that
this game will not primarily target children
under the age of 13. Then select ads in
newer versions, Unity removed the D tab. It's not visible. If you
don't see it, don't worry. Just follow the lecture. We connect game
IDs through code. Here you can notice
Android and IOS game ID's. We need to get them
through gaming services. Now let's get back
to Unity dashboard. After you sign in, make sure that you selected
the right organization. Organizations have projects, we need to choose the Space
Shooter mobile project. Go to Unitization. Click on Get Started. I only plan to use Unity ads. Choose a Fresh start. Our app is not alive yet. Then we can create
monetization project. You can see IOS and
Android game ID's. Go to Ad Units. Here you can see three types
of ads For IOS and Android. We can use banner rewarded and interstitial ads
more about them. In the next lectures, go back to Unity. You should see game IDs
here if you don't see them. Restart Unity. Great to use ads, we go through three steps. We need to initialize ads, load ads, and then show ads. Let's do the first step, initialization for
organization purposes. Let's create one empty
game object, Ds. Then let's create
a new game object. I call it ads controller. Create a new folder for scripts. The first script will be adds, initializer, add the script
to the object and open it. I will also provide a link
to the documentation. Here is the initialization part. You can copy paste the
whole script if you want. I will create it step by step and add one modification
at the end. First, let's clean up
what we don't need. Then we need to include
Unity engine advertisement. After we need one interface called Unity is
initialization listener, then we need to implement
that interface. This will create the own initialization
complete function. That is called when
the process is completed and one function
when it fails to complete. Let's use the bag logs
so we know what happens. I will copy paste this D bag
from the example script. Let's create some variables. We need string game IDs, one for Android and one for IOS. Then we need one bull
variable test mode. The last one is
the string game ID that we need to assign. Let's create a public
function initialized as it's a public, because maybe you will
call it in another class. Here we need to assign
game ID to Android or IOS. I will use a short version of the if statement in parenthesis. We check if the application that platform is equal to
run time platform, that iphone player then
write a question mark. If we are on iphone, then use IOS game ID.
Then write colon. If we are not using phone, then use Android game ID. Now we can use the advertisement
initialize function. Use the game ID that we set. Then choose test mode. We need to pass the
initialization listener, which is this object. Now let's create
the awake function. Here we call initialize ads. We need to do initialization
only once in the game. The best time to do it is
usually when we start the game. Note that you don't need to have this object in every scene. Do it once you are good to go. However, if initialization fails and you want to try
it in other scenes, then it's a good idea to check
if the initialization is already done, then return. And don't try again. Go back to Unity. Here we need to set IDs. You can copy them from the
Unity dashboard or go to Project Settings and
copy paste values. Be careful not to mix them
then since we are testing, let's enable test mode. Don't forget to disable
this before you build the publishing version of
the game. Let's try it. You can see in the console the initialization is complete. This is all for the first step. In the next lecture, we cover banner
ads. See you there.
65. UPDATE: Unity Cloud: Hello guys. This is
a quick update about Unity gaming services
or now Unity Cloud. If you have problems finding Unity aids monetization
in the new Unity cloud, this video will help you, you need to sign in
to the Unity Cloud. You will see the
new dashboard here. You will find your projects. You can also create new ones. But we need Space
Shooter Mobile. Let's open it. Then you can click on the
Shortcuts Plus button, search for Aids, and choose
Unity Aids Monetization. Here you have all the tapes that we need, including ad units. Another way of finding the monetization section
is to open products, search for Unity ads
and open monetization. Nice, Now you can continue
with the course monetization. See you in the next lecture.
66. Banner Ads: Hello again. In this lecture, we create banner ads. Let's prepare some things. We can copy an empty object, go to the level you want
to enable the banner. I will do it in the
level of oscillations. Tin, paste the empty object, create a new empty object, call it banner eight. Then we can create a new script. The name will also be banner ad, the script to the object. Now, if you open the link that you can find
in the resources, there is a section
for banner ads. There is one example
script on how to implement banner
ads with buttons. We will use a
different approach. So we can just copy
paste the code, as in the previous lecture. We will use some parts. When implementing aids. We need to know Ed IDs
for Android and iOS. So how do we get ones? Go to your dashboard, select monetization
and open ed units. Here we have all the types. We can select banner ads. You can see the name
and ID of the ad. We have one for Android
and one for iOS. We can also create
a new ad units. Choose a name and applied firm. Then you can choose
what type unit. Now you should see your
edit unit on the list. Just to show you, you
can go to edit settings. Here if needed, you can
change some settings. We will not use this banner ad. I just wanted to show
you the process. Let's send it to the archive. We will use the default ones. Remember, it's important to
know IDs back in the script. The goal is to load and
show the banner ad. First, we need to include the
advertisements namespace. Then let's create two
id string variables, one for Android and one for iOS. We can set default values. Note that it's a better idea to copy paste so you don't
make any mistakes. Then we need a
string, a unit ID. Next, we can create a banner position variables so that we can choose
where to show the ad. In the start, let's
set a unit ID. We use hash if Unity, iOS, which means we are
using an iOS device, then set IRS ad unit ID, then a hash L if Unity Android. Of course, here we use
Android ad unit ID. Close this with hash. And if we don't need
the update function, create a public void, load the banner ad. First, let's set the position. Then create banner load options. Here we use a load callback that will trigger their own
banner load function. We will create it in a moment, use a coma and create error callback that will trigger their own banner error function. Let's create those
two functions. Own banner error will happen
when something is wrong. So we can just use
the bug Datalog. Own banner load will trigger when the Earth has
finished loading. Before we do anything here, we need to actually
call the load function. So back here, after
the options we made, we use advertisement banner that allowed and we paste the
ID with the options. Then when the banner ad
is loaded and ready, we show it using
the show function. Of course, we need to pass ID. Now, we just need to call this a load banner ad somewhere. It depends on the
game and your choice. I will call this
function in the start. So when we start the level, we should see the banner. In Unity. Makes
sure that ideas are correct and choose
the banner position. Let's try it. In Unity editor. It's hard to see it. In a real game. It will be bigger. Let me just zoom in a bit. You can see it here. If you see any errors, make sure that the initialization
step is completed. So try to test it by starting the game
from the first scene. Here we do initialization, go to Level Selection, and the banner is here. Now you can create a prefab. You can place this prefab
in any level unit. You can place it
in multiple levels and everything will
function fine. Let's just create one, a safety measure in the script before we
load and show the ad, Let's check that
advertisement is initialized. Nice. Note that everything that
we had done in this script, you can do it in the
initialization script. I just wanted to separate the content so it's
easier to understand. Thanks for watching and see
you in the next lecture.
67. Skippable Ads: Hello again. In this lecture, we
create interstitial ads. Those are ads that a
player can escape. The idea is to create
an ad that will appear after playing
a few levels, e.g. we play one level when we restarted or go
to another level, one interstitial ed is played. Of course, you can choose
how often an ad will appear. Now, we can start with
the implementation. We are still in the
level solutions team. Let's create a new game object. I call it interstitial aid. Then create a new script. Also call it interstitial, add the script
object and open it. We also have documentation to
implement interstitial ads. There is a lot of content here. I will copy one part
and then we will modify it and go step-by-step. Let's copy this part that
includes the Aid ID. Just make sure that it IDs match the ones from the
Unity monetization. If you go to monetization, you can select interstitial. And here you can see IDs
for Android and iOS. If you want, you can
create new ad units here, but I will use the default ones. Now, let's take a look
at the awake function. We assign an id by checking if we are on iPhone
or Android device. You need to be careful
about one thing. In the Unity editor, this will always use Android ID, ID, even if you
choose iOS built, the ID will be for Android. Because we are not using iPhone. We are on Mac or PC. Repeat, this is only
in Unity editor. In a real game, it
will function fine, but that makes it hard to test ads for iPhones in the editor. So if you want to test Ed's for iOS devices in Unity editor, you need to use a method
that we used in Banner Ads. Let's copy paste this part. Then, comment this part. Of course, you don't
need to do this. This is just a small
digression for testing. Let's continue. We need the
advertisements namespace. Here we need two interfaces. The first is allowed LA Center, and the second is
Chablis scenario. Let's implement functions. We have a function that is
called when the load is completed and one when
it fails to complete. Let's implement functions
for the listener. This one is when we
click on the Add. This one is called when
the aid is completed. Then when the fails to show and when the
head starts to show, we will modify some
of them later. I will just move
these functions down. Now, let's create a public
void load ed function. We check if advertisement
is initialized. If that is true, then load the ED with the ED ID. And this allowed listener. Then create a public
void show Ed function. Here we use the show function, paste the ID, and
this show listener. Let's use a load ed in awake. You can choose when
to show the ED. I will show it immediately
after the loading is done. Let's try it. We start the test from the first scene because
here we initialize Eds, go to Level Selection. And you can see the ed. However, we need to
solve three issues. First, the game is still
running in the background. We need to stop it. The second thing, we
need to hide the banner. The last thing we need to choose how often this will appear. You don't want it
to play it every time the player
changes laborers. To make testing easier
from the start, seeing, let's create
the aids controller. Prefab controller is
responsible for initialization. Go to a level of selection. Plays the prefab into the scene. If you test it directly
from Level Selection, still the aid will not run. We also don't have
the banner ad. This is because we
do initialization, loading and showing at the
same time in awake or start. Initialization takes some
time to complete and loading gets called before
industrialization is finished. That's why we usually don't initialization in
the first scene. So keep that in mind. We need to create the
interstitial, a Prefab. Then we can copy it. Objects, go to
level one and paste them to place these
three objects into every scene in
which you want ads. Let's test it. Start from level selector. Go to the first level. You can see. Notice that you can hear shooting
in the background. Now we need to address the
three issues I mentioned. In the interstitial, a script find on Unity aids, show start. When we start the ED, let's stop the time. And by setting the
time scale to zero, this will stop the
game from running in the background while
the AED is playing. When the AED is completed, we reset timescale to one. Then let's disable the banner. When we start the AED, use advertisement,
that banner that hide. Show it again, we need a reference to the
banner ed class. Then in Show complete, use a load banner ad. Go to unity, select interstitial ed and
dragging banner ad. Then taste it from level of
selection to the first level. Notice there is no
banner ad. Also. You can't hear shooting. For some reason, the
background music place, but this is a bug
in Unity editor. Let's skip the ad. And now you can see the banner. Nice. The last thing, we
don't want to show interstitial ads after
each level of change. So let's create one
integer time to skip and set the
default value to one. This number will determine
how many times we can reload or change the level
before we show the ad. Next in awake, create one
integer, skip number, and use player prefs, get into the k will
be interstitial. Default value is the
time to skip number. Then check if the number
is different from zero. If that is true, decrease it by one. Next, save that number. Else. That means that skip
number is a zero. Then we need to load
and show the ED. Then reset the value for
the interstitial key. Let's try it. From start seeing
we go to Level Selection. Usually we would
have the head here, but skip number was one. Now it's reduced to zero. So after the next load, we should see ads go to
level one and we have ads. Now, let's destroy the player. We should reload without aids because skip number
was reset to one. If we lose the game
again and restart it, we will see it. Nice. Everything works. Note that you can
adjust the time to skip number in Unity
or in the script. That's all for this lecture
and see you in the next one.
68. Rewarded Ads [1]: Hello everyone. Let's create a reward
add that will give an option to continue the game after the player is destroyed. It looks like this. We'll lose the game. We get a panel with
the Play button. We watch one, Ed, and then we can
continue playing. Of course, we will
limit how many times a player can do that. Let's start create a
new empty game object. I will call it rewarded ed. Then create a new script
with the same name. The script to the
object and open it. We can also open
Unity documentation. The link is in the resources. There is an example script. We will slightly change
the implementation. So don't just copy
paste the whole script. We can copy this
part for Aid ID. Just delete the part
with the button. Now make sure that I
these are correct. Go to your dashboard
monetization, select rewarded ads, and you can see IDs for Android and iOS. Of course, you can
create custom aid units. Here. We will use the default
ones back in the script. To use the advertisements
namespace. We also need a load listener and show listener interfaces. As before, let's implement
functions from interfaces. Let's clean it up first. If you wish, you can use the
backlog in the functions. I will skip that this time. Let's move those
functions to the bottom of the script. Nice. Now, let's create a public. Load, a function. It's public because
maybe you will need to call it somewhere
outside of the script. Then we can use
advertisement load with an ID and this
allowed listener. Before loading, Let's check that advertisement
is initialized. We can call it in awake. Then let's create a public
show, the function. Here, we use
advertisement that show with an ID and this
show listener. Now we need to choose
when we will call this show Ed function and
what will happen, then. Some of the logic will be in the show start and show
complete functions. In the show complete function, we give a reward to the player. In our case, we will revive the player and he will
continue to play. Every game is different, so every implementation
is different. This is why I decided to do the actual implementation
in a separate lecture. This is just a template
and basic preparations. So see you in the next lecture in which we implement
the main logic.
69. Rewarded Ads [2]: Hello everyone,
welcome to part two of implementing a rewarding ads. Now that we have a
solid foundation, we can actually create
a domain, a logic. The idea is to have
the possibility to watch one on skippable ad after the player is destroyed and
then continue the game. This lecture will
be a bit longer because we need to
address a lot of things, not just the ED. So maximum concentration
for this one. First, we will need a reference to the player and banner ad. When we start showing
a rewarding ed, we need to hide the banner. Also set timescale to
zero to freeze time. Then let's choose what happens when the rewarding
aid is completed. We use the if
statement and we use this placement ID to
check the ID or the ED. So we make sure that we work with the correct rewarding it. Then we check the
completion State, which is the status of the ad. Use Unity aids, show
completion state. As you can see, we can check for the completed script
or unknown state. We need completed. This condition will ensure
that we execute the code only if the correct
rewarded ed is completed. Then resume time by
setting timescale to one. Then we can activate the player. Note that we will need
to change the code in player stats so that we don't
destroy the player object. Instead of destroying it, we will disable
it and enable it. Here. We need to, again a load and
show the banner ID. Next, we can prepare and
allowed the next, rewarding it. In Unity, dragging the
banner ad and player. Then we can go to player stats. As I said, here, we don't want to
destroy the player. So comment destroy. We will deactivate the player. Of course, we need to solve how reset variables every time we enabled the player, e.g. we need to reset health, health bar and so on. That's why we replace
start with ONE enable. Just move player shooting, get component in
the start function. Let's go to unity. Now, let's create a screen
that will have one button. The screen will appear when
we deactivated the player. Go to Canvas, select panel, and change alpha to one. Then select Screen
and duplicate it. Rename it. Then enable it. Double-click on
panel and zoom in. Let's create a new button. I will call it, play it. Delete the text,
we don't need it. Then we can change the sprite. Go to sprites. You choose this
orange play button, drag it into the
source image field. Click on Set native size. The size is good. Now we need to
arrange the elements. Let's expand the
background a little bit. Move the score and
highscore down, and move the add button up. This looks good. Now let's open the panel
controller script, which controls the
win and lose screens. We need to add the
ed screen we made. So we need another
game object variable. I call it a loose screen. As before, let's create a public function that
will activate it. Set Canvas alpha to one, and activate the game object. In this case, we need one more function that will
deactivate the screen. Set alpha to zero, and deactivate the game object. Back in Unity. Don't forget to drag the Ed Lewis screen to the
panel controller script. Now select the play button. We need to add functions
to this button, Create to onclick events. For the first drag
the panel controller. Here, we need to
deactivate it, lose. So when we press this button, we will deactivate this screen. Then dragging the
rewarded Ed object called The Show add function. We can deactivate the screen. Now. Select panel and
return alpha to zero. Let's go to the end
game manager script to implement more logic. Scroll down and create a new public function,
Ed Lewis game. Here we use panel controller and activate the edit screen. We need to be careful because a player can decide not to watch it and restart the game
or leave to main menu. So we need to use the score set function that will save the score
in highscore. But it will also reset the
score variable to zero. This will cause
problems if a player decides to watch an ad
and continue playing. I have n is a solution for this. Let's change the
access modifier of the score variable,
make it public. Then go to rewarded ed. When the head starts, we can load the score. Use PlayerPrefs that get int. The best idea is to
copy paste the key. So here we save the score
before we erase it. Let's copy the key
and paste it here. Okay, we're not done, but we can test this. In End Game Manager. When we lose a game, let's call the aide
Louis game function. Note that we will change this if else statement in a moment. This is just for testing. Let's start from
level of selection. Go to level one, and let's lose the game. You can see this score, the high score, and
the Add button. Let's click on it. We watch one ad, and when it's finished, we can continue the
game a bit full health. Notice that the score just continues to increase,
its not zero. However, at this point, we can watch the ad every
time we lose the game. That is not what we want. We need to limit this option. It needs to appear maybe
just once or twice. Just want a small digression. Sometimes if you try to test this directly from level one, you will get one error is
because on Enable function, End Game Manager Instance
is not created yet and we try to use
it to solve this. Go to Project Settings. Then script execution, order. The end, the game manager
script to the list, then move it above default time. It should have a negative value. Now the script will be
executed before other scripts. That means the instance
will be created before we try to call it in their
own enable function. You can see there
are no errors now. Great. Before we continue
with other stuff, Let's add some protection
time to the player. When the aide finishes, go to player states,
create a public. Bool, can take them as variable, set the default value to true. Then let's create one
eye enumerator function. Set can take damage to false. Then we wait a little bit. I will go with 1.5
s. After that, we set can take damage to true. In the player tag
damaged function, we check if can take
damage is false. Then return and don't
damage the player. In the own enable function. Use start coroutine to call the damage
protection function. Nice. Now, I want to give additional protection
to the player when we showed the windscreen. In End Game Manager, let's create the player
states variable, which I call player. Next, let's create one function
to register player stats. This is the same procedure is for other register functions. Set player two states, player, then go
to player states. And in the start function, let's register this player
stats to the manager. In End Game, Manager. In the game, a function set
can take damage to false. When we showed the windscreen, nothing can happen
to the player. Now, we need to update this if else statement with
some conditions. Just to remember you, this is important
for this concept. When we defeat the boss
or we reach the timer. First, we wait a little bit of time before resolving the game. It's because of bullets and enemies that can still
be on the screen. Now, when we implemented aids, there is a case
where the boss and player can be destroyed
at the same time. Also, the player
can be destroyed at the end of a level under this 2.5 s. We are at
the end of a level. We don't want to
show a the screen. We need to show a loose screen. In that case. That's why we introduce
a new variable. Let's create one public bool
variable, possible wind. So how do we use this variable? Let's go to the wind
conditions script. When the timer has
expired and we don't have a boss then set
possible when to true. When we have a boss, then we need to go to
his boss that state. When we destroy the
boss, set possible, when the true back
to the manager. When possible, when is true? That means we defeated the
boss or the timer has expired, and GameOver is false, which means we didn't, they activate the player, then we want the game. Next case. Else, if possible,
when is false, which means we are not
at the end of a level, but we deactivated the players
since game over is true, then we want to show a screen. We need another else. If so, if possible, when is true and
game over is true. That means the player is the activated at the end of a level. Then don't use a screen, just a loose screen. I will just put comments so
it's easier to understand. Since end the game manager
is aesthetic singleton. We need to reset the possible when variable in another script. We can go to player stats. In start. We can set it to false. So every time we start a level, it will be false. Now, we need to limit
the number of ads. Let's create a reference
for rewarded ad. Then create a function
to register it. I call it register rewarded at. The procedure is
the same as before. Go to the rewarded ad script. In the start function, let's register this object. Then let's create a
public int number. By default, it can be one. That means we can only
watch one, rewarded it. Back to End Game Manager. In the Ed Lewis game function, we check the number of ads. If it's greater than zero, then show the ad screen and
decrease the number by one. Else. We don't have any left. So use panel controller
to activate lose screen. Now we can try it. I will have only one ad. Let's play the game
and lose it. Once. Watch the ad. Then continue
to play and lose it again. We don't have any left. So we see Louis screen. Nice. You can create a
rewarding a prefab. Also don't forget to override
changes to the canvas. And we are done. If you need, you can add
some logic when the aid fails to show this is
specific for every game, but now you have an idea
of what you need to do. Things for watching and see
you in the next lecture.
70. Android Notifications: Hello everyone. Let's see how we can create notifications for
Android devices. First, make sure that you
use the Android platform. Then go to Package Manager,
select Unity Registry, and search for notifications, select mobile notifications
and click Install. Now, let's create a
new empty game object. I will call it
Android notification. Then we need to create a script. To stay organized. I will create a new
folder notifications, create a new script and call it Android
example notification. The script to the
object and open it. First, we need the unit in notification
android namespace. Now, let's create
some variables. We need one integer
notification ID and one string
channel ID example. Next, let's create a public void notification
example function. It will take one
parameter, date time. With date time, we
can manipulate time and determine when to
send a notification. To better understand it, we can debug it. I can say e.g. that time. Now, which will give me
the current date and time. Just convert it to a
string so we can see it. Start the game. And in the console, you should see the current
date and time as a string. Nice. Then we need to do two steps. The first is to create
a notification channel, and the second is to create
an actual notification. Let's start with the
notification channel. Use Android
notification channel, and create a new instance. First, we set the channel ID. Here. We can paste
the channel id example variable
that we created. Then we can give a
name to the channel. Next, we can have a description. It's not really important
for what we do. Then we can set importance. The importance of
notification is used to determine how much
the notification should interrupt the user. You can see what
every option does. I will go with the default one. After we created a
notification channel, we need to register it. So use Android
notification center, that registered
notification channel pays the channel
that we created. The second step is to create
Android notification. Create a new instance. First, we can set the title, then the text of
the notification. We can also choose
small and large icons. For the notification. I will use the default icon, which is unitary logo. So how to change them? Go to Unity, project settings
and mobile notifications. Here you can add notification
icon support Android. You can choose small
enlarge icons, and every icon has a
string identifier. So e.g. if you set a small icon with the
example identifier, then you would type that
identifier in the script. The last thing we
need is a fire time. This is the date time when the
notification will be sent. Here we use the
parameter time to fire. The notification is done. Now we need to fire it. We use Android
notification center that sent a notification, paste the notification
channel ID. Now, we need to determine when and how to
schedule notification. For our purpose, we will
use on application focus. Their own application
focus function has one bolt parameter focus. This function is called when the application loses
or gains focus. That means when we
minimize the application, the parameter focus
will be false. When we maximize or
entered the application, focus will become true. So our idea is to schedule the notification when the player minimizes
the application. After some time, we will tell the player to come
back and play. So if the focus is false, we can use date, time, set it to
the time that now, and then we can add time. As you can see, we can add days, hours, minutes,
seconds, and so on. Let's add one day from
the current time, which will be when the player
minimises the application. Then we call
notification example and pays went to fire date time. If the player returns and open the application before the
notification was sent, then we need to cancel the
scheduled notification. We can cancel it with ans red notification center that can sell all scheduled
notifications. And again, when a player
minimises the application, we will add time and schedule
another notification. Note that this will cancel
all scheduled notifications. I will show you how to cancel just this notification up here. When we send the notification, we can instead use send
notification with explicit Id, paste the notification
channel ID. Then we need to paste
the notification ID. If you remember, we created
a variable for this. So pays the notification ID. Then instead of canceling
all scheduled notifications, we can use scheduled
notification and pays the notification id. Great. For testing purposes. Let's not use this. Instead, just add 10
s. We're not done. We have one important
thing to do because we will build this
game for Android and iOS. This code will give us errors
when building for iOS. To solve this issue, we need to compile the script only if we are using Android. So first, let's solve the
android Notification namespace. We use if Unity Android
and close it with hash. And if. Now this line of code will be compiled only for
Android devices, we also need to do the
same inside the class. We don't need the bulk that log before the notification
example function. If Unity Android and close it after the own
application focus function. Now we are done. If you want, you can
create variables with default values and paste
them into the function. In Unity, you can change values, then create a prefab and place
it in every sin you wish. Let's build the app on
the phone to test it. Building to phone is covered
in previous lectures. So check it if you didn't. Okay, now we are on the phone
and let's open the game. Go to the level
of selection sin. Then we can minimize it. And in 10 s, we should
see the notification. As you can see, it's here. Click on it, and we
are back in the game. You can use this
knowledge to create different types
of notifications. And that's all for this lecture. Thanks for watching and
see you in the next one.
71. iOS Notifications: Hello everyone. Let's create notifications for iOS devices. The logic will be the same
as for Android devices. Just the syntax is different. If you didn't watch the
Android notification lecture, I suggest you do it
before watching this one. Note. Just one important thing to test notifications
on your iPhone. You need to have an
Apple developer account. It cost $99 per year. So keep that in mind. Okay, first, let's switch
the platform to RS. Then go to Package Manager, select Unity Registry,
and search for the mobile notifications
package, then install it. If you didn't. We did it in the
previous lecture. Then go to Project Settings, select Mobile Notification,
and go to iOS. Enable request authorization
on a per launch. That will open a
dialog popup window when a player enters the
game for the first time, then a player can
allow notifications. This will save us a lot of work. Otherwise, we would need to
do it ourselves in the code. Now, let's create
a new game object and call it iOS notification. Then create a new script, which I will call iOS
notification example. The scripted the
object and open it. The idea is to create a
notification that will invite a player to come back and play the game after some
period of time. First, let's use the unit in
notification, iOS namespace. We don't need default functions. Let's create one string
variable, notification ID. Next, create a public void
notification example. Here we create an iOS
notification instance. The first thing we
assign is identifier, paste the notification ID. Then we can set the title
of our notification. We also have the subtitle. Then we have body. This will be a text
for the notification. The next property is
show in foreground. If set to true, it will show a notification. Even if the application is open, our notification will invite a player to come back and play. So we need to set it to false. Just to show you if you plan
to make another type of notification and you set
that variable to true, then you can choose foreground
presentation option. If you're type of
presentation option, you can see alert, badge, none and sound. Basically, you choose what type of notification it will be. You can also use combinations. So you can e.g. choose Alert and then write a
vertical aligned. We use two of them
for logical OR, but here we write just one. Then I can also use sound. The next property is
category identifier. You can group notifications
into categories and then do some operations that will affect all notifications
from the same group. It's not that
important in our case, so set it to category a. The next thing is
thread identifier. Also, it's not important
for what we're doing. So let's just follow
the documentation. It will be thread one. Then we have one
important property. It's trigger. It determines when we will
send the notification. So let's create a new iOS notification time
interval trigger. Then set time interval to
new system, that time span. Here, we can choose to add days, hours, minutes,
seconds, and so on. To choose one day, we change this to one. But for testing purposes, let's use 10 s. Then we need to set repeats to false so
that we don't repeat it. This notification every 10 s. After we created the
notification, let's schedule it. Use iOS notification
center that schedule notification and paste
the notification. Then we will use the own
application focus function. For more details
about that function, check the Android
notifications lecture. But essentially,
this focus parameter becomes false when we
minimize the game. And true when we
maximize the game. When we minimize the game, we want to call the notification example that will schedule the notification. If the player
returns to the game before the
notification was sent, then we need to remove it. You remove scheduled
notification and pays the notification ID. We are almost done. If you want, you can
create the variables and then paste them
into the notification. The last thing we need to
do to prevent errors is to compile this script only
if we are building for iOS. First, let's solve
the namespace. We use hash if Unity iOS and
close it with cash. And if. Now this line will be compiled
just for iOS devices, we need to do the same
inside the class. Go to unity. We can set the variables
in the Inspector, then create a prefab and place it in every scene you wish. As I said to this
notifications for iOS, we need to have an Apple
developer account, which I currently don't have a. If you have one, you can build the game on the
phone and tested. Building on the
phone was covered in previous lectures
in the course. That's all for this lecture. See you in the next one.
72. Profiler: Hello everyone. In this lecture, we take a look at
how to use profiler and detect possible
performance issues. We will also learn how to use profiler directly
with your phone. Let's start go to Window
Analysis and Profiler. We should see
something like this. First, makes sure that
the record button is on. Then enable the profiling. Deep profiling enabled. The profiler will
analyze every part of your script code and it will
record all function calls. Then we can choose
how we want to see Data Select Hierarchy. Next, place this tab
somewhere down like this. And we can extend it. When we press the Play button, we should see some
data on the graph. Data is measured frame-by-frame. If we press on any frame, the game will pose and we can see details about
that specific frame. You should look for spikes since they indicate
a performance drop. Just remember that
spikes are normal when loading and
changing levels. Things you should look for our garbage collection
and time in milliseconds. Note that you can
ignore editor loop. This is from Unity editor. It will not exist when
you build the game. We can even remove
that data from the graph by disabling others. Notice that every data is
presented by one color, e.g. scripts or dark blue. Also, you can keep an eye
on FPS on the left side. Now about the data, we are interested
in player loop. So expanded for more details. Here you can see data from all sorts of scripts
and packages. We can find the
scripts that we made. Go to update that script, run behavior, behavior update. Just notice that we don't
have any problems here. There is no garbage collection and the time is really short. You can see update
calls from our scripts. E.g. here is update
from meteors pounder. There is player
controls and so on. Of course, you can expand
it to get more details. Remember, it is important
to comment or delete, debug logs before building
and publishing the game. To show you why I created one object with the
script, find me. It only has the
bug log n update. Let's run the game. Select any frame,
find the script. You can see that the backlog
creates some garbage and it takes 0.13 milliseconds
to dispose of it. Keep that in mind. However, we are making
a game for phones. So testing on a PC will not
give you the real picture, especially if you have
a really good PC. I will show you how to use
profiler with Android devices. For iPhone, it is
a bit different. So I will put the link to the documentation to use the
profiler with your phone, go to File, Build Settings, connect your phone and
select it as device. I have one old who
away for testing. Then enable development
built out of connect profiler and deep
profiling the support. Then you can click on Build
and the run or pitch and run. Wait until everything is done. The game should run
on your phone and the profiler should
automatically run. If you don't see any data,
expand display mode, go to local devices
and choose your phone. If your game is running, you should see data. Note that this data is from
your game on the phone. We expect some spikes
and drops in performance when going from level to
level and that kind of stuff. That is normal. Select any
frame and define the script. Where is debug dot log? You can see find the
update and debug log. It creates garbage and slopes
down the game on the phone. So don't forget to
delete debug logs. It's a good idea to test
the game on more phones. So invite your friends and see how it feels on
different devices, more phones, the better. The goal is to detect garbage collection
and other problems. If you find them, then you need to think about how to improve and optimize scripts. Sometimes it's possible
and sometimes it's not. Every game is different. That's all for this lecture. See you in the next one.
73. Object Pooling: Hello everyone. Let's optimize
the game a little bit. As you know, when we shoot, a lot of bullets are
created and destroyed. That can be a slight
problem for older devices, so we need to address it. The idea is to create
object pulling. Imagine that we have a
pool with game objects, in this case bullets. They are instantiated
but inactive. When we shoot, we get a bullet from the pool and activate it. Then we don't destroy bullets. We return them to the
pool and reuse them. Let's see how we can
apply this in our game. Select the player and
go-to player shooting. We will use unit is built
in object pulling method. It's relatively new. We use the Unity
engine pool namespace. We need to replace this game object type with
the script that bullets use, and that is a laser bullet. Remember the name of this
variable, blazer bullet. Next. To create an object
pool variable. Inside pointy brackets, we
choose the type of this pole. E.g. you can have a
pool of game objects, but we need a pool
of laser bullets. I will call it pole. Then we need to create a
new instance of that pool. In the awake function, use new object pole and a laser bullet type between
the pointy brackets. Then open and close
the parenthesis. You will notice that we have one error is because we need to create some functions
for the pool and pays them
between parenthesis. So the first
function is in which we instantiate the
object we need. The second function is used to take the object that we created. We call it by writing
the name of the poll, which is pole in our case, then that gets the third
function is used to return the object
to the pole and we call it with Paul that release. Let's create the
first function that will create objects
for the poll. This function needs to return the same type as the poll type, which is laser bullet. I call it create a poll object. Here. One instance of
the laser bullet. So instantiate laser bullet
with the position and rotation of the player
when creating an object. Position and rotation
are not important in our case because
we change them later. Sometimes it can be
important and it's a good idea to create objects
outside of the screen. So keep that in mind. Then we return the bullet. Paste that function into the
pool inside parenthesis. Now, let's create
a function that will take objects from the poll. I call it, take
bullet from Paul. It needs to take one
parameter, laser bullet. When we take a bullet, then let's activate it. Here. Sometimes you can set
the position of the bullet, but since we will use
multiple positions, leave it like this. Then let's create
a function that will return objects to the poll. I call it on a return
bullet from Paul. Also, it has one
parameter, laser bullet. Here, we need to
deactivate the bullet. Now, paste these
functions to the pole. Next, we need to tell
bullets to use this poll. So go to the laser
bullets script. Now, we don't destroy bullets, so we can comment out destroy. Here. We also need the pole namespace. Create one polar variable
of laser bullets. I call it reference pole. We need to connect this
pool variable with the pole instance we created in the player
shooting script. To create a public
void set poll function that will take as a parameter
pool of laser bullets. Then set a reference pool to pool the player shooting script. When we create one laser bullet, let's use bullet that said Paul and pays the pool
from this script. Now, every bullet has a
reference to the poll. Let's see how we shoot and get
the bullets from the poll. We don't need instantiate. Here we just use pull that gate. This will call the function on. Take a bullet from pool, which will activate the bullet. Now we need to set the
shooting position. We can just say that transform, that position equals two basic
shooting point position. So we activate the bullet and place it in the
desired position. For now, let's
ignore other cases. Let's go back to the
laser bullets script. Now we need to implement
the activation of bullets and return
them to the pole. Instead of destroying, use
reference pole that release. And we want to
release this object. This will call on a
return bullet from pool, which will deactivate
the bullet. Of course, we need
to repeat this in the own became
invisible function. Here we need to be careful
because we don't want to call the function or the object that has already been released. E.g. when the bullet is
the activated, here, it becomes invisible and we
call a release again. Here. This will give us an error. To prevent this. First, let's check that
the bullet is active. Now, when we deactivate it here, this will not be called. But when the bullet goes off the screen, it's still active. Then they activate it. So everything should
work. Let's try. It. Just makes sure that you have the laser bullet
prefab assigned. As you can see, we
can spend bullets, but there is one problem. When we create bullets
for the first time. They have speed, but when we reuse those bullets,
they don't move. Let's fix it. Go to the laser bullets script. Replace, start with ONE enable. This is called every time
we enable the bullet, let's try it now. As you can see, we reuse the
same bullets and they move. If all created
bullets are active, they will create a new one. Nice. Let's add more
functions for the poll. We can also define a function
that will be called when we need to destroy a bullet from the pole and that can happen. I will show you an
example in a moment. Create onDestroy Paul object that takes the laser
bullets parameter. Here. Let's destroy the
bullet game object. Paste that function to the pole. Then we can choose true or false for the collection
check variable. If set to true, the pool will check for double release calls
that I mentioned. Let me show you. We can comment this line
of code and test it. We expect errors to show up because of double release calls. Play the game a bit and
you can see the error. Trying to release an object that has already been
released to the pole. That's why we have
this condition. Later I discovered that if a bullet hits more
enemies at the same time, then this release can
also cause errors. So plays the same
if statement here. I will do it later. Then we can choose the default capacity and
maximum size of the poll. Let's go with ten as the
default and 30 as the maximum. The default value determines how much memory we
want to reserve. Reserve memory for ten
objects from the pole. And the maximum that
we can reserve is 30. It's important to
understand that if we use all three objects
and we need one more, that object will be created
with this function. But when we return
it to the pool, it will be destroyed
with this function. So you can have more objects
that your maximum value, but they will be destroyed. You need to find the
right balance for default and maximum
value for your game. Now, let's finish
the short function. Replace instantiate
with Paul that get used the same positions as for the Instantiate Canaan and
write cannon positions. I will speed up this process
until the last case. The last case, we need a different approach for the list to
instantiate functions. Since we also need to
change the rotation. We will save the instance into a variable when we
get it from the pole. Then we will set the position. And then rotation. After we changed a rotation, we need to set the speed
and direction of a bullet. So go to the laser
bullets script. Here, we create a public set, direction and speed
the function. Repeat the code from the
own enable function. For laser bullets
that have some kind of rotation on Enable
will be called, but it's called before
we set the rotation. So we need to call this function after the rotation is set. Here, we use bullet one that
set the direction and speed. To repeat the process for
the second rotation, 0.1. Last thing, we need to reset
the rotation of bullets. Use on disable. Here, we just set a
rotation to zero. Before we finish,
I will just place another if statement
that I mentioned before. Let's try it. As you play the game, you can see that the bullets
become active and inactive. We don't destroy them, just disable and enable them. We have no errors. Everything works just fine. You can use this object pulling the method in other
places in your project. E.g. if you spend
a lot of meteors, you can go to meters pounder and create a poll for meteors. That is all for this lecture. Thank you for watching.
74. Android Build for Publishing: Hello everyone. After you finish the game, it's time to publish it. The first step is to
create an Android build that we can upload to
the Google Play Store. Let's start. Go to File, Build Settings. Make sure you use the
Android platform. Don't forget to add the scenes you want
to be in the game. Then open player settings. Here you can set
your company name. The product name will be
the title of your game. Let's change it to space. Shorter course. We can ignore the
version for now. Here you need to
add a default icon. If you go to icons, you can see specific API levels and overrides for the icon. Expand one of them and you will see the sizes for your icon. Let's go to resolution
and presentation. Here, you can choose the
orientation for your game. In this game, we need portrait. Then go to splash image. Here you can add your logo. When the game starts. Just click on the plus
button and add the sprite. I will quickly show
you how this looks. Nice. There are a lot of options. You can change the
background color, you can change the duration. Also, you can show logos
one-by-one and so on. This is how it looks
one by one logo. Next, go to other settings. Here we have a lot of
important options. Scroll down and find the
identification subsection. First, we needed to
make sure that we have the correct
package name format. Usually it goes like this. Com dot your company name, that name of your
game. It is correct. You can see just a warning that invalid characters
have been removed, which are spaces
in the game name. You can also override your default package
name if you wish. I will leave it like this. Then we have version. If the game is completed, use 1.0 or if it's beta version, then you can use
zero-point. Some number. Bundle version should be one. Now, this is important when
you plan to update your game. You need to change
the version e.g. to 1.1 or something. It just needs to be different
from the previous one. And you also need to increase
bundle version by one. If you don't change numbers, you will not be able to publish
an update on Google Play. Keep that in mind. Then you choose the
minimum API level that your game will support. I will leave the
minimum API as it is. Then you have the target
API level option. The Google Play has a
minimum target API level. It changes over time. You can check it
online, just google it. The point of creating
this lecture, this is what Google says. The best approach is to choose the highest level
API that you can. The next requirement
for Google Play is that applications need to have
ARM 64 target architecture. As you can see,
we can enable it. So change scripting backend, and now it's enabled. Then let's go to
Publishing Settings. We need to create a KeyStore. And key. The key is some sort of certificate that you are the
owner of the application. Click on key store manager, then KeyStore, Create New. And I will choose anywhere, choose a name for the K star. Now we add a new key, create a password,
then choose alias. It's some kind of
identification for the k. Then you can use the same
password. Click on Add. Kay. Great. Let's go back to Build Settings. We need to check built
a bundle, Google Play. Now we click on Build, choose your location
and file name. This will take some time, especially if you are doing
it for the first time. When the build is finished, you will have one AAB file. We use it to publish the game to Google Play that is covered
in the next lectures. So see you there.
75. Privacy Policy: Hello everyone. Before we get to the
publishing lecture, let's create a privacy
policy for our game. If you plan to have
ads in your game or your target audience group
is children under 13 years, Google Play requires you
to have a privacy policy. There are a lot of
policy generator sites. I will show you one example. The link will be
in the resources. First, you will put the
name of your application. Then your e-mail is
contact information. Next, you can put
the information you collect for our game directly. We are not collecting anything, but we are collecting
third party services, which we resolve in the next
section of this generator. So I will leave this empty. Choose your app type, then choose your
target platform. This game is for Android. Then you choose whether you are an individual or a company, and enter your name
or company name. Click on the Next button here. You should see the list
of third-party services. If you use some of them, just check the boxes. We use Unity. Click Next. Now you should see the
terms and conditions and privacy policy
document generator. We need the privacy policy. So this is the text
of our policy. Note that a link to your third party services and
their policy is included. We need to publish this policy. So let's copy the whole text. Search for Google Sites. Again, the link will
be in the resources. Create a new blank, cite. The title can be privacy policy. The site name can be the
name of your application. Then paste the text. Check that everything is
here and click on Publish. Choose your web address, and finish the process. Now, we can view this page. Great, we have a privacy
policy for our game. It's a good idea to create a button in your game that will open this link and lead
a player to this site. But that's another topic. See you in the next lecture.
76. Google Play Forms: Hello everyone. In this lecture, we fill out and go through
Google Play forums. This is a necessary step
in the publishing process. So first, you need to go to
the Google Play console. It looks something like this. Go to Play console. You will need to create
a developer account. It costs $25 and it's
a onetime payment. After you create your account, you will be directed
to this page. Click on Create app. Then enter the name of your application and choose
the default language. We need to select game. Is it free or paid? It's free. Then accept the terms
and click on Create. You will be redirected
to dashboard. Here you have three
main sections, tasting, setup, and release. First, let's go through
the setup section. We will go step-by-step
through this bullet list. Note that I will
enter information based on the game we
made in the course. Every game is specific, so some choices and information can be
different for your game. Let's start with
the privacy policy. Instructions. Say, we must add a
privacy policy if our target audience
includes children under 13, I will not target audience. But when using EDS, we still need to do this. So in the previous lecture, we made a privacy policy, copied the link to that page. Then click Save. Go back to dashboard. You can notice the
green checkmark when the step is completed. Let's go to the next IP access. Users don't need to create
an account to play the game. We don't have any subscription
model or something. So choose that all
functionality is available without any
access restrictions. Save it and go
back to dashboard. Next is the EDS section. Yes, our app contains Ed's. Some of these forms are really short and some are a bit longer. The most tricky is data safety. So don't miss that. Let's go to content rating. This is a bit longer task. Also, enter your email
and choose a category. Then click on Next. Now, we need to answer
some questions. This is specific to
every game in our game. If we don't have any
violence or blood. There is no fear factor. Now, sexuality and gambling, basically, all of these
answers would be no. Click Next. And submit. Go to Target audience. Choose age groups. Just note that for this game, we could include
children under 13, but then make sure that in
the unit that is section, you choose the right option. Next, we'll this game be
appealing to children under 13. Let's say No, that is a bit
questionable, but okay. Google will review it
and you can change your answer next and save it. This is not a news app. Then COVID-19, we don't
have anything with that. Now let's go to Data Safety. Yes, we collect and share data through
third-party services. This data is encrypted. Yes, users can
request to delete it. Every aid for immunity has this icon in one of the corners. If users click on it, they can request
UNITAID to delete data and some other options. Next, here we need to select
all data that is collected. How do we know that if
you use unit the aids, then we can take a look
at Unity documentation. This is the Google Play
data safety section for unity ads. I will put the link
in the resources. On this page, you can see what
data types are collected. E.g. let's take a look at
this location section. We collect approximate locations and we don't collect
precise locations. Back in Google Play Console. Select approximate location. Next is the personal
info section. Go to Unity documentation. Look at the personal
information table. The only data that
is collected is the user's personal identifiers. So select users IDs. Now just follow the tables from Unity documentation and you will manage to select the
correct options. Note that if you use some
other third party services, you should find a similar
tables and data on their sites. So you can correctly
fill out this form. After you finish
this, click on Next. Now we are in the data
usage in handling section. For every option we select it, we need to provide
more information. E.g. let's start with location. Again. We look at the table. Location is collected
and shared. This is no data collection is required and you can see the purpose of that
data collection. So check both boxes. This is now and this is yes. Then check purposes and select boxes that
match the table. Save it. You can proceed with other data, go to personal info, find the table, and
repeat the process. After you finish, click
on Next and submit. This is not a government app. The next two tasks are for presenting your app
on Google Play. Go to the first one. This is, again,
choose your category. Our game would go in the
action category. I guess. Here you can add
tags. I will skip it. Then enter your contact details. You can also add your website. Save it. Open the last task. Here you have the name, short and full descriptions that will appear in
the Google Play Store. Then you need to
upload your icon. This icon should match the
icon that you set in unity. We also need to upload
the cover image. Note that you can see the correct dimensions for
each image at the bottom. If you have a YouTube
video about the game, you can place the link here. Then you need to place screenshots
or phones and tablets. I will speed this up, save it, and we are
done with forums. In the next lecture, we'll learn how to set up internal testing
for our game and help to actually publish it
on the store. See you there.
77. Google Play Internal Testing and Publishing: Hi everyone. In this lecture, we'll learn how to add
tasters so they can download the game before other people
and of course test it. Then we'll learn how
to publish the game. Okay, first, go to
internal testing. Select the taster step. Let's create a new email list, a name for the list. Then you can add the
e-mails of your testers. You can add yours, of course. Save changes. Then goto releases. Create a new release. Here we need to upload
the AAB file that we created in the previous
lecture, drag it in. This will take some time. When it's finished. Make sure that the earliest
name has the correct numbers. You can write some release notes and give information
about this release. Then click Next. You will notice one error. We need to complete
one more declaration. If you use unit the EDS, this should be yes. Then select these three
options and save it. Go back to internal testing. We don't have any errors, so we can start a rollout
to internal testing. Again, go to tasters. Down here, you should
copy the link. This is the link you should
send to your testers. Using that link, testers can download your game and test it. To publish the game. Go to production. Open the Countries tab. Go to Edit countries. Here you can select in which countries you want to
publish your game. Let's select all of them. Then goto release tab. Create a new release. Since we already
uploaded the app bundle, we don't need to do it again. Click on Add from library. Choose the bundle we uploaded
for internal testing. Make sure all
information is correct. Click Next and then start
roll-out to production. Confirm rollout here. I will not do it because I'm not going to actually
publish this game. But when you press this
button, it's done. Then you wait a few days. And if everything is good, the game will be published
on Google Play Store. If you want to publish the
game on a specific date, then go to publishing overview. Here. Turn on
managed publishing. In this case, once Google
approves your game, it won't be published
automatically. You will have to
publish it manually. And that's it guys. You know how to publish
a game on Google Play. Copia will create amazing games and that this course helped you. Thanks for watching
and have a nice day.