Unity Mobile Game Development | Mario Korov | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Introduction

      1:59

    • 2.

      Create a project and choose settings

      2:12

    • 3.

      Device Simulator

      1:15

    • 4.

      Sprite Importing and Sprite Editor

      3:23

    • 5.

      Scrolling Background

      7:31

    • 6.

      New Input System Setup

      1:43

    • 7.

      Enhanced Touch Fundamentals

      4:43

    • 8.

      Move Player with Touch

      7:07

    • 9.

      Player Movement Restrictions

      4:48

    • 10.

      Camera Boundaries

      5:34

    • 11.

      Touch Controls Update [Don't skip]

      4:47

    • 12.

      Tap Count

      1:44

    • 13.

      Virtual Joystick

      6:36

    • 14.

      Enemy Concept

      5:38

    • 15.

      Meteor Prefab

      7:17

    • 16.

      Collision Matrix

      2:57

    • 17.

      Meteor Spawner

      7:30

    • 18.

      Object Rotation

      1:24

    • 19.

      Player Shooting

      8:47

    • 20.

      PlayerStats and Damage System

      3:15

    • 21.

      UI Fundamentals

      4:19

    • 22.

      Health Bar

      7:09

    • 23.

      Safe Area Helper

      2:58

    • 24.

      Explosion Animation

      5:36

    • 25.

      Damage Animation and Transition

      6:18

    • 26.

      Shooting Enemy

      12:49

    • 27.

      Green Enemy

      1:45

    • 28.

      Enemy Spawner

      3:40

    • 29.

      Win Condition

      4:05

    • 30.

      UI Panel Controller- Text Mesh Pro

      5:13

    • 31.

      Game Manager

      8:39

    • 32.

      Singleton Pattern

      3:02

    • 33.

      Change Levels/Scenes

      8:41

    • 34.

      Fade Between Scenes

      9:05

    • 35.

      Loading Screen

      5:55

    • 36.

      Upgrade/Fix Fade Effect

      2:32

    • 37.

      Font Creation

      2:17

    • 38.

      Score System

      6:09

    • 39.

      Playerprefs Syntax

      2:32

    • 40.

      Save and Load Score/High Score

      7:37

    • 41.

      Scene Preparation

      3:49

    • 42.

      Start Screen (Menu)

      4:21

    • 43.

      UI Setup

      5:54

    • 44.

      Level Selection and Unlocking

      7:55

    • 45.

      How to easily create levels

      2:22

    • 46.

      Android Phone Build for Testing

      3:26

    • 47.

      iOS Phone Build for Testing

      6:14

    • 48.

      Scriptable Object Spawner

      6:15

    • 49.

      Health Power Up

      4:39

    • 50.

      Shield Power Up

      9:22

    • 51.

      Shield UI

      5:42

    • 52.

      Shooting Power Up

      8:34

    • 53.

      Power Ups Update

      0:38

    • 54.

      Boss Concept and Preparations

      2:25

    • 55.

      Boss States and Controller

      4:23

    • 56.

      Enter State

      6:02

    • 57.

      Testing States

      2:21

    • 58.

      Boss Fire

      7:47

    • 59.

      Special Attack

      12:33

    • 60.

      Boss Stats and Death

      8:22

    • 61.

      Spawn Boss

      4:32

    • 62.

      Background Sound

      2:26

    • 63.

      Shooting Sound Effect

      5:07

    • 64.

      Ads Setup

      9:00

    • 65.

      UPDATE: Unity Cloud

      1:15

    • 66.

      Banner Ads

      6:53

    • 67.

      Skippable Ads

      10:03

    • 68.

      Rewarded Ads [1]

      3:41

    • 69.

      Rewarded Ads [2]

      16:32

    • 70.

      Android Notifications

      9:38

    • 71.

      iOS Notifications

      7:03

    • 72.

      Profiler

      5:14

    • 73.

      Object Pooling

      12:32

    • 74.

      Android Build for Publishing

      5:18

    • 75.

      Privacy Policy

      2:41

    • 76.

      Google Play Forms

      8:07

    • 77.

      Google Play Internal Testing and Publishing

      3:46

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

110

Students

--

Project

About This Class

This course is made with Unity 2022 version. Lectures are carefully edited, concise, and easy to follow. There is no time wasting. To follow the course you will need some basic C# knowledge (variables, functions, "if" statements, etc.) and you need to be familiar with the Unity editor.

The Space Shooter mobile game is designed to guide you step by step through challenges that can occur in mobile game development. You will learn how to make your game compatible with all screen resolutions and devices (automatic Camera adjustments, scaling and placement of UI elements, and more).

Some highlights of this course:

  • New Input System

  • Monetization

  • Notifications

  • Optimization

  • Device Compatibility and Testing

  • Boss Fight

  • Publishing Process

By the end of this course, you will have general knowledge of how to develop and publish mobile games.

(*please note that the publishing process is covered only for Android, on Google Play Store, the rest of the course covers both, Android and iOS)

I respond to all messages if you get stuck anywhere or need help.

You can also join the community on the Discord server and connect with other enrolled students.

(Link to the Discord server is in the Resources file)

Thank you for your time and see you in the course lessons.

Meet Your Teacher

Teacher Profile Image

Mario Korov

Game Developer | Teacher | Mathematician

Teacher

You can find more tutorials on my YouTube channel: RootGames

Hello everyone, my name is Mario and I'm a self-taught game developer with a Bachelor's degree in Mathematics from the Department of Mathematics, Osijek.

For almost a decade of freelancing, finding quality and short tutorials was my major stepping stone, so I decided to put all my knowledge and passion into unique, straight-to-the-point videos to help other developers. You will save so much time, learn faster, and in the end make a game faster.

To sum up, all my love and passion are in Unity courses with the goal to help you in your game developer path. Thank you and see you in the lessons.

I'm really looking forward to this journey.

See full profile

Level: All Levels

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

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.