Unity 2D Master: Game Development with C# and Unity [Part 2/2]- Main Part | Mario Korov | Skillshare

Playback Speed


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

Unity 2D Master: Game Development with C# and Unity [Part 2/2]- Main Part

teacher avatar Mario Korov, Game Developer | Teacher | Mathematician

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

75 Lessons (4h 54m)
    • 1. Introduction

      1:16
    • 2. Project Setup and Download Files

      0:27
    • 3. Importing Sprites

      1:42
    • 4. Importing Pixel Art Sprites

      3:15
    • 5. Sprite Editor and Sprite Sheet + [Mini Challenge]

      2:16
    • 6. Tilemap Setup

      4:27
    • 7. Placing Tiles and Layers + [Mini Challenge]

      1:31
    • 8. Tilemap and Composite Collider

      1:29
    • 9. Preparing the Player

      2:08
    • 10. Controls Setup -New Input System

      5:57
    • 11. Moving the Player- New Input System

      8:51
    • 12. Flipping the Player

      3:24
    • 13. Animation Setup

      4:00
    • 14. Animation Transitions

      6:10
    • 15. Player Jump

      3:06
    • 16. Ground Detection

      6:34
    • 17. Challenge+Review- Ground Detection

      1:36
    • 18. Jump Animation with Blend Tree

      5:39
    • 19. Double Jump and Additional Jumps

      2:47
    • 20. Fix Sticky Walls

      2:06
    • 21. Controller Setup

      6:42
    • 22. More About Controllers- Avoid Mistakes

      4:47
    • 23. How to upgrade Unity Version (Upgraded to 2020.3 LTS)

      1:21
    • 24. Main Camera Info

      2:40
    • 25. Cinemachine Follow Camera

      6:47
    • 26. Pixel Perfect Camera

      1:40
    • 27. Fix Lines/Gaps Between Tiles

      1:47
    • 28. Camera Boundaries

      2:07
    • 29. Collect Gems using Tags + [Mini Challenge]

      4:39
    • 30. Sound Basics

      1:18
    • 31. Add Sound to Pick Up (Gem)

      1:54
    • 32. Challenge + Review- Background Music

      1:02
    • 33. Canvas Setup

      2:17
    • 34. Image and Text Setup

      3:21
    • 35. Display Gems Number

      4:42
    • 36. Health and Damage System

      4:35
    • 37. Damage Prevention Time using Coroutines

      3:01
    • 38. Spikes

      4:07
    • 39. Hurt and Damage Animations

      3:04
    • 40. Spikes Knockback

      5:32
    • 41. Health UI

      5:38
    • 42. Challenge + Review- Health Pick Up

      2:13
    • 43. Enemy Concept with Parent and Child Classes

      4:39
    • 44. Move Enemy

      5:06
    • 45. Enemy Attack

      5:58
    • 46. Change Levels/Scenes

      4:48
    • 47. Fade Between Scenes

      8:56
    • 48. Game Manager Setup

      7:44
    • 49. Unlock Doors with Game Manager

      5:58
    • 50. PlayerPrefs Syntax

      2:43
    • 51. Save and Load Health

      3:41
    • 52. Challenge- Save Gems

      0:42
    • 53. Challenge Review- Save Gems

      1:16
    • 54. Moving Platforms

      6:57
    • 55. Move Player with Platform

      1:45
    • 56. Platform Upgrade

      1:40
    • 57. One Way Platform

      2:13
    • 58. Player Melee Attack

      11:23
    • 59. Challenge + Review- Enemy Damage Animation

      2:13
    • 60. Play Attacking Sound with Animation Events

      1:27
    • 61. Challenge + Review- Destructible Box

      5:20
    • 62. Climb Ladders

      10:43
    • 63. Particle System- Gem Particles

      6:58
    • 64. Main Menu Preparations

      1:34
    • 65. TextMesh Pro + [MiniChallenge]

      4:50
    • 66. Buttons and Main Menu + [MiniChallenge]

      10:27
    • 67. Challenge- Custom UI Controls

      2:11
    • 68. Pause Game + [Challenge]

      3:41
    • 69. Load Saved Level (Continue Game)

      2:15
    • 70. Export/Build Game

      3:23
    • 71. URP Setup

      3:23
    • 72. 2D Lighting

      5:21
    • 73. 2D Shadows

      0:48
    • 74. Post Processing

      6:15
    • 75. Screen Shake with Cinemachine

      3:55
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

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.

42

Students

--

Projects

About This Class

(Note that this is PART 2 of Unity 2D Master Course)

This course is made in Unity 2020 using Unity's newest tools and packages. I promise you that this is one of a kind course with short, informative easy-to-follow lessons. No time-wasting, that's why I call it Time Saver.

The 2D Platformer class is the main part of the course in which you learn how to fully utilize the new input system with controller support.

The class will also start as beginner-friendly but it will slowly lead you into advanced programming techniques and solving complex tasks (melee attack, climb ladders, inheritance, virtual functions, lists, singleton pattern GameManager, etc). It will give you a foundation and a great concept on which you can build your games.

In the end, make your games stand out with 2D lights and post-processing effects (third part/class)

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

You can also join the community on the Discord server (the link is in PART 1) and connect with other enrolled students. Also, don't forget that this course will expand over time and you can vote for the next lessons.

Trust me, you won't be disappointed.

Thank you for your time and see you in the classes.

Meet Your Teacher

Teacher Profile Image

Mario Korov

Game Developer | Teacher | Mathematician

Teacher

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. Through six years 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

Class Ratings

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

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

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: Welcome to the Unity 2D master course. This is part 2, and we'll learn how to make a 2D platformer game before we start, I want to point out that this course is a time-saver license are short straight to the point. The 2D platformers section is the main part of the course. It will also start as beginner friendly, but it will gradually lead you into advanced programming techniques to expand your C-sharp knowledge, and more importantly, how to apply. You will learn how to use unit is new as toes have to quickly create maps with Talmud. Have to create player moment with the new input system and you can show your support. Also, you will learn how to fight enemies, make the multiple objects, moving platforms have to implement sound effects in much more. Of course, you will get to know the UI system and help to make Main Menu. In the end, make your games thinned out with the particle system to the rights and post-processing effects. Value discourse is something different from anything you have seen before in, I'm really looking forward to teaching you how to make games. So we joined it twice today and see you in the lessons. 2. Project Setup and Download Files: To start the town Mp3 2D platformers section, you need to create a new 2D project. The next step is to download the files from the resource folder. When you downloaded files, use a winner are or similar program to extract them. And that's it. When you downloaded and extracted the files, you are ready to proceed. See you in the next lesson. 3. Importing Sprites: We can import sprites in two ways. The first way is to go to Assets, import assets, and allocate sprites you want to use. For this example, let's import soldiers pride. It should be in your downloaded files, press Import, and now you can see it in the assets folder. Of course, you can choose multiple sprites, eight ones, but there is another way to import assets that I usually use. You can just drag and drop the whole folder. Let's use the sprites folder. Note that all sprites are PNG files and let's move the soldiers sprite in the sprites folder and use it in the scene. You can see that everything looks good as it should. But if you try to use pixel art, for example, this door, you will see some problems. Press F to focus on the door. The first thing you will notice is that the door is blurry. Why is that? Let's select the soldier from the assets folder. And in the Inspector, you should sit in poor settings. Default settings are good for non pixel art and usually you don't need to change anything, maybe wanting, you want to keep in mind, and that is max size. A good practice is to write the size of your sprites in the name. This sprite is 512 times 512 pixels. Notice if I set max size to a smaller number, the sprite, he'll become blurry. You need to set max size to at least your original size, which is 512. In this example. For pixel art, we must change more settings, and that is the next lesson. 4. Importing Pixel Art Sprites: Okay, let's take a look at import settings for pixel art. First is the texture type, and that is sprite end UI by default, sprite is a 2D graphic object, so that is the correct setting. The most important thing for pixel art is to set the filter mode to point and set the compression to non mix size is greater than the original size. So we can click Apply. You can see that this looks much better. The next important thing is pixels per unit. Unity has something that we call a world in units, they are measured in the scene world. This one square is one world unit. By default, we have 100 pixels per one unit. To help you understand how this works, you can check the size of this door. It's 64 by 48. If I set pixels per unit to 64, the door should be one unit wide because the original width size is 64. The reason why the size is not from bottom to top is that the original height size is less than 64, it's 48 exactly. Another example is the sword. Original height is 24. So setting pixels per unit to 24 means that the sword will take one world unit from bottom to top. Notice how pixels from the source are much bigger than pixels from the door. This is because the sword has less pixels per unit. So pixels must be bigger to fill the world unit, and also it's smaller in original size. To avoid this problem, we must import all sprites with the same pixels per unit number. How to determine the best number? Usually, you look at the original size of your tiles for platforms or your character sizes. In this project, we use 16 by 16 size, and that is why the correct number is 16. For this project, the most common pixels per unit numbers are 8, 16, and 32. This is something you need to decide before you start making art. Change pixels per unit for the door to 16. Notice how the door is bigger and pixels are the same size. Also, you can select a multiple sprites and change iep or settings for each sprite in one step. The next thing we need to look at is sprite mode. By default, it's single for the sword and door, that is the correct mode. Multiple mode is when you have a sprite sheet, which means multiple images combined in one. For example, these gems pride. We need to set sprite mode, the multiple, and then slice it in the sprite editor, that is material for the next video. You can go through the sprites folder and set the correct input settings for all sprites. Change pixels per unit, filter mode and compression. 5. Sprite Editor and Sprite Sheet + [Mini Challenge]: When we have a sprite sheet, we need to set sprite mode to multiple and then go to Sprite Editor. In the Sprite Editor, we can slice this spreadsheet into separate sprites. Go to slice. By default, type is automatic. The automatic mode we'll search for edges of sprites and slice around them. We can use it to see how it works. Click on slice and you can see that spreadsheet is divided. If you click on the sprite, you can see details and more options that you can change. Usually, we don't use automatic mode. Sometimes it will not give you the result you want. Here. It will be good because it spreads head the same size, dimensions of error and Jim are the same. But let's take a look at how we usually slice in the spreadsheet. Sprites are arranged in a grid so we can slice them by cell size, change type two grid by cell size. I know that this spreadsheet has a 16 by 16 grid. That information you need from the artist who made art in this project. Every spreadsheet contains cell size in the name so you can easily identify it. So set pixel size to 16 and slice it. Click, Apply and exit to the Sprite Editor. Now, you can click on this Expand button and you can use a gem sprites one by one. This will be used for the animation of James later. Let's see how we slice the sprite sheet for Change Settings and go to Sprite Editor. Now, if you try to slice with automatic mode, you will get three sprites. This is the example when automatic mode isn't good, we want each block separately. So again, slice with the cell size of 16. This is what we wanted, each small blocks separated. Your challenge is to slice other spreadsheets in the folder for tile map. And when you finish, See you in the next video. 6. Tilemap Setup: When you have sprite sheet ready, it's time to use them in Tower map. Make sure that 2D Tile map editor is in your project. To create the Talmud, go to 2D object tile map. And here you should see different types of townships. In this project, we use a rectangular type. This will create the township and grid. Grid is the parent object of every town where you can look at townships as a sorting layers in some way. Notice that Tom IP uses tile map render instead of sprite renderer in additional settings, we have a layer, a control death we will use later. The next step is to open tile pellet with this button. Or you can open the pellet window if you go to Window 2D Tile Palette. Now, we just follow the simple steps we needed to create a new pallet. Let's call it ground pellet. Grid type is correct. We can click Create to organize this project. Let's create a folder for pellets and save it to there. The next step is to drag some sprites in the pellet to create a sprite assets. Use platform sprites. Also create a folder for Sprite S. Now we have some sprite assets in the pellet that we can place on the tarmac. It's important to keep an eye on the active tile map because here we choose ONE which Talmud we want to play styles for now, we have only the ground tau map. At the top, you should see brushes and if you hold the mouse over them, you will see short keys. Let's use the paintbrush to play some tiles. You can experiment with the brushes. Also, it's possible to select tiles with the select tool and move them with demo tool. Of course, there is Erase tool. You can also edit pellet, click on Edit and arrange towers as you wish. Also, it's possible to erase the tile from the pellet. To add a new tile to the pellet, go to sprite assets. Find the right asset and just place it where you want. Don't forget to exit the edit mode. Now, let's prepare things for level painting. We need another township, middle ground. Duplicate it and create a beggar around town. If you take a look at active tile map, you will see that now we can choose a township on which we play styles. Let's choose a background tower map. And let's create another pellet that will hold the tiles for the background and middle ground together. Same procedure as before. Just drag and drop a bare ground sprites to create assets, create a folder for them. We also want to use beggar and decorations, books and dead stuff. Let's organize the pellet or bit and we are ready to use it. Make sure that active tile map is background. However, you will notice that the background taus overlap ground tiles. This is because we need to organize the layers, which we do in the next three there. Check the reminder and see you soon. 7. Placing Tiles and Layers + [Mini Challenge]: As I said, you can consider a tile maps as layers. Let's create sorting layers so we can organize tau maps. I will add three layers, background, middle ground and the ground. To recall the layer at the bottom, all delis will be first on the screen. Now, select the ground down, up and said sorting layer to ground. You can see that the ground is now in front of the background. Let's select them. We know grounds township and sets the middle ground sorting layer. Of course, the beggar and township will be on the bare ground, saltier layer. Now I can select active tile map, middle ground, and the place is some books. Your challenge is to make one room. It should be big enough for the player to move and jump around. Always pay attention to active town. So you don't make styles for different elements. Plays, books, and in lights on the middle ground is tau map. I also put some shading styles at the background. To conclude, the thermal package is a really powerful tool. It will speed up your project significantly. This is how I made the room. Nothing complicated. Few decorations, place to jump. So give it a try, explore a little bit, and see you in the next three days. 8. Tilemap and Composite Collider: Let's prepare a thiamine for collision so the player can move on the ground, select ground tile map and add tile map collider 2D. Let's will create a collider for each tile on death star map. As you can see, we have a collider for every tile. This will create collision between objects. But to improve performance, we need to merge these colliders in one collider for debt, we aid composite collider 2D component unit. We will also aid the rigid body 2D because it's a necessary component in combination with composite collider. Now, we can set tau map collider to use by composite. You can notice that colliders merged in one big Collider. If we press Play, the ground will fall because of gravity. Remember to set the rigid body type 2 Static. Also in composite collider, you can change geometry type two polygons. Sometimes a collision is better detected with polygon type then just outlined the end. The result is one big polygon collider and static rigid body. 9. Preparing the Player: Let's prepare the player for the next license. You should slice player sprites in the Sprite Editor, the grid size is 100 pixels, as you can see in the name. Now use the first sprite from the idle sprite sheet. Notice that the player is behind the background. We need to change the sorting layer. Of course, you can just move default layer down or create another layer. It's better to create a special layer for the player. The next thing we need to do is to add rigid body 2D. Remember, if you need better collision for the player, you can always change detection from discrete to continuous. I will skip it for now. Then you can add a collider, for example, box collider, 2D edit collider so it fits the sprite. Now, the player will collide with the ground. Great. But you need to be careful when using books colliders to move the player because of the edges, a vertex of the collider can get stuck between colliders in the ground if they are not from one part. This is an example. We have ground made from two colliders. And because of small errors in calculation, the collider of the player can get stuck at intersection even if the ground is perfectly flat. So it's better to use something ground for the bottom of the player. You can use a circle collider and combine it with the box collider or any other. The lightest. And my favorite solution for this sprite is to use a kips of 2D collider. You get two. In one, the shape is good and it's round at the bottom. Now the player is ready for input implementation in the next video. 10. Controls Setup -New Input System: Before we start anything important, the input package, go to Package Manager and search input system. Click Install, and then we'll do the rest. Now, we can create something we call input actions. Right-click. Create input actions. Let's call it controls. Double-click it and a new window should appear. As you can see, we have three sections. Action map's actions and properties. Action map determines for what or who will use controls. To create an action map. Click on the plus button. For example, an action may for the player or to control UI. Each action map has actions. By default, you will see one action and one binding. Action determines what you want to do. For example, jump, shoot, move, and so on. Binding is like a trigger. You set the button that will trigger action. Let's delete this action and create a new one. This action will be for jumping. Then select the binding and go to path. Here, you can choose what you need to press to trigger the jump. For example, you can go to keyboard and find space. Also, you can search the baton in the search field. The best way for me is to click lesson and just press the button I want to use. Select the space button. It's possible to add more bindings toward action. For example, I want to jump when I press the up arrow. If you select action jump under properties, you will see action type. By default, it's a battle, in this case, is the correct setting. For some other things we use value or pass through, we use space through later for the mouse and UI things. Let's use value for the move action, create, action, move and set Action Type 2 value. Under control type, you can specify what you want to use from Bhutan value x is the PET vectors and so on. We will use x's value, but you can set it to any. Let's add x is composite binding. For negative biding set a and four positive set the or use a left and right arrows. Under Properties, you can see the minimum and maximum value and which side will win if we hold buttons at the same time. Let's go through some more settings so that you can see what you can do with this new input system. Under processors, you can set a dead zone, which is useful if you are using controllers. And there is also an option to interact controls and so on. For now, we won't use this. If you go to jump action under interactions, you can set hold time. That means how much time we need to hold the button to start the jump. Usually, you don't want this behavior on the jump, but I want to show you what you can do in general with this input system. You can change the whole time or use default one to change the default input settings. To open the input settings. That will open the project settings window in the input system package, click on Create settings acid. And then you can change the default dead zones, hold time, and other settings. Below, you will see the supported devices section. And as it says, leave it empty to support all inputted devices. If you want to specify support to only a few devices, click on the plus button and choose what devices you want. I recommend that you leave this empty. It will support all devices. It can. Notice that this whole time will affect all bindings for the jumping action, but you can override it for specific binding. Default, time for jumping action is 0.4 seconds. But we can select the up arrow binding and set the whole time to two seconds. You can customize it as you wish in your projects. For this project, let's delete the up arrow binding and remove whole time from jumping action. The last thing in this lesson, you need to click on the Save As button. You can turn on the outer save option if you want. I don't use it because when you make more changes, it will save every step of change and it will slow you down actually. So this is the first part of the new input system. The next step is to create scripts so we can actually use everything remained in these controls. Show you the reminder and see you in the next part. 11. Moving the Player- New Input System: In this part, we start to write code in scripts to move the player. The first thing we need to do is to select controls, input actions, and generate a C-Sharp class. That means that Unity, we'll create a script based on the input actions we made. Click apply. And you should see the script in your Assets folder. We don't use that script later. It's just something you need to do. So if you open it, don't be scared in that script, unity hard-coded every setting from controls. Note that you need to generate C-sharp class only one time if you make changes in your input actions, the only thing you need is to save it. It will automatically update the script. Now, select the player. We need to add a player input script. It's the script from the input system package. In the field, actions, use controls. Make sure you use input actions, a set and not generated script. And as you can see, you can choose default action map. We have player and UI. The next step is to create a folder for scripts. Create a script, gather input, and edit to the player. The script to be used to gather inputs from controls that we made. The first thing we need is the input system package. Then we need to create the controls variable and float variable to store some information. In the awake function, we need to create a new instance of controls. Then in their own enabled function, we need to enable controls so we can use them. The own enabled function is called after awake when the object with the script is enabled. Also, if you are not familiar with the function institution order, check the execution order lesson in C-Sharp and new in the basic section. Notice that we can enable all action maps by writing my controls that enable, or we can enable just action map that we want. For example, let's enable just the player action map. If we don't enable action maps or controls, we came to use them. Now, we need some way to get values from the inputs. The input has a value from minus one to one. And idea is to use that for direction left and right. For debt, we use private void function start, move that has one parameter, input, action dot callback context. From this context, we can get values from inputs, store them, and use them as we need. And let's store a float value in the value X variable, right? Ctx, that read the value angle brackets. We won't flow to ALU and the parenthesis followed by a semicolon at the end. To complete this step, we need to assign this function to the corresponding action map in the own enabled function, right? My controls, the action map player that action move that. And now we choose the phase for the action. Here is a table of phases. You can check the link to this page in the resource folder. We want the face performed, which happens when we press the button associated with the action. And preformed means that the action has been completed. So we use performed phase and then assign the start mode function to this action with plus equals sign. It's just like we assign variables, but in this case, we assign function. That is a lot of information at once, but it's pretty simple when you learn syntax. We create controls, enable them, and we assign this function to actually move with phase performed through context. We stored the value of that action to variable value x. This script will be just for gathering inputs. And let's create one more script where we use that stored input and move the player with rigid bodies. I will call it player move controls. Here, we do something familiar that we did before in the course in physics lessons. We need variable speed. Variables gather input and rigid body. In the start function get components. Of course, we move the player in the fixed update. Use the rigid body and new vector for the x value. Multiply the speed by value x to get inputted direction for the y-value, set it to RB dot velocity dot y. In that way, the velocity or y axis will be just under gravity influence. Let's try this in Unity. Setspeed to any positive number and press Play. As you can see, we can move, but we have some problems. First is the rotation. It's on the z-axis. In rigid body constraints, freeze rotation. Problem one is sold. The second problem is when we stop pressing buttons, we continue to move because we didn't clear inputs. You can see that value x has a value of the last pressed button. To solve it, we must go together. Input script, create another function, stop, move and set value x to 0. The next step is to assign this function to face canceled. In that way, when we stop pressing buttons, the value will be 0 and the player will not move. Great. We are almost done. There is one hidden problem. Let's use debug dot log in the start-up mode function. Now press Play and delete the player. Tried to press the Move buttons. You can see in the console that functions are called, even when the player is destroyed. Functions that we assign to actions not live on the player. So we need to disable them when we destroy the player. Or we can get the weird behaviors and errors. The input script inside their own disabled function. You can disable the player action input. Of course, you can disable all controls. Also is good practice to remove functions from actions with minus equal sign from the performance. Phase removes start to move from the cancelled phase, remove stop mode. Finally, we are done. You can show this in Unity. Everything should work. If I stop pressing buttons, the player will stop. And if I delete, the player, functions won't be called. I know that this is maybe a lot of information, but this is because the syntax is new. The next video is about animations, and later we make a jump for the player. You will see that it will be a lot faster and easier. Check the remainder and see you in the next video. 12. Flipping the Player: Before we start with animations, Let's quickly flip the player idea is to change the scale to a negative number and to flip it back, set the scale to a positive number in the player controller script. And let's create one into variable direction and set the value to one. Value one means that the player is facing right and negative means that the player is facing the left. By default, the player is facing right and that is why reset the value to one. Let's create a new function. Flip. Inside the function, check if the product of input and direction is less than 0. So for example, direction is one and we press input to move arrived, then the value of x is one and the product is positive, nothing happens. But if we press a button to move left where your x is minus 1, then the product is negative and we enter the if statement. Here, we need to flip the player using transform local scale. For the vector value on x, set the local scale to the opposite with a minus sign minus transform local scale that X. This will flip the player, as I showed at the beginning, we are changing the x component from positive to negative or from negative to positive. Four the y and z x is set the radius to one. Now we are facing left and we need to change direction value multiplied by minus one, so direction will be negative. Let's say we now press a button to move right, where your x is one and direction is negative. Product is less than 0. We again flip the player. Now it's facing right again. Then we multiply direction with minus1 and direction becomes positive. That is actually all we need to do. Call the function inside fixed update. Now we can show it in Unity. Everything works fine. Let's go back to the script to organize functions creatively, to move a function. Sometimes you can have problems with this autocorrect and suggestions. Escape to cancel them. Select the Flip function and RB dot velocity hold out and use down arrow to move them inside demo function called demo function in the next update. And that should be it. We are done with flipping the player, but let's change the play mode color. So in the future we can easily see when we press the Play button. Great, That is all for this video. 13. Animation Setup: To start animating the player, we need to open the animation window, go to Window Animation, and choose the animation window. Next, it's important to select the object, in this case the player. Then we can click Create, make a folder for animations. In this case, we want either animation. Let's take a look at what we did. As you can see, now the player has an animator component, which we need for animation. An emitter needs an animator controller and unity created one automatically. Click on it. You can see in the animations folder that we have the player animator controller and idle animation. When created automatically, the animator controller name is determined by object name, in this case, player. We also created the animation idle. And in the Inspector, you can see some settings. We usually just uncheck allow time for the animations that we don't need to repeat. In this case, we need to repeat either animation while the player stance. It's time to set up the animation. Go to Player sprites, select the player again and just drag idle sprites in the animation timeline. Now, we created keyframes, and each keyframe is one sprite. Let me just zoom in and turn off gizmos. Press play in the animation window and you can preview the animation. As you can see, it's too fast. Just select keyframes and split them a bit more. It's better, but it's still too fast. You can split them even more. But let's take a look at some options for the timeline. It's possible to change the timeline scale two frames instead of seconds. You can see 60 frames in the timeline. I like to use seconds. So this is 1 second and either animation is 0.2 seconds. The next thing we need is a sample rate. The sampling rate, the default number is 60, which means 60 frames per second. To slow down animation, we can set this to a smaller number, for example, 30. This is much better. I forgot to mention that you can zoom in and out of the timeline, Richard, the mouse wheel. Before we continue, let's make a small adjustment. The animation will be 0.18 seconds, so the keyframes are divided evenly into play mode. You can see that idle animation is playing. However, it's playing, even when we move the player. Let's create another animation. Click on idle and create a new clip. This will be moved animation. Use sprites. Press Play to see Preview. Also, it's too fast. Set sample rate to ten, and this should be good. If we go to play mode, again, nothing is changed. We can see just the idle animation. We need to create transitions between animations and this is material for the next video. Check the reminder before you continue. 14. Animation Transitions: To transition from one to another animation, we need an animator window. Select Animator window. Again, same as timeline. You can navigate to it with the mouse wheel. Now you should see two animation states. Either end, move. Don't mix these animation states with animations. For example, let's select the Move state in the Inspector, you should see the field motion. In the motion field, you can choose an animation for the animation state. In other words, the animation state contains an animation clip. When you create a new animation clip, as we did in the last video, the animation state for that animation clip will be created automatically. This is why we have idle and move states with corresponding animation clips. We can also create a new state with a right-click. Create state empty. This will create a new empty state with no animation clip. Of course, you can add any clip that unit. I hope you see the difference between states and animation clips. We don't need this now. So let's delete the empty state. As you know, in the play mode, we could only see the idle animation. This is because the idle state is set as default state. You can see it because of the orange color and transition from the entry, it's possible to change that. Right-click on the Move state and choose Set as a layer default state. Now, you would see only the move animation. Of course, we need idle as default. Let me just organize states a bit. To create animation transition. Right-click on the animation state idle and make transition. Now click on the Move state repeated the process. But now from moved to Iowa State, click on the transition from idol turmoil in the Inspector, you should see transition settings and transition timeline. By default, the transition is not instant and you can see it in the timeline, this overlap area, usually this is for blending 3D animations. So we need to remove that and set instant transition. That means that when we start to move, play the animation immediately under settings, set the transition duration to 0. You can see that transition is instant. In the next step, we need to decide how to trigger an animation transition. You can see that Has Exit Time option is enabled. And if I said Exit Time 2, 1, the transition will happen when either animation completes one cycle. If I set the number to 0.5, as you can see in the timeline, that transition will happen in the middle or the idle animation. But we don't want to play either animation once or health or the animation and do the transition. We need to repeat idle animation. And when a certain condition is met, then do the transition. So we can turn off exit time and fixed duration. Now you get a warning. We need at least one condition. For the conditions, we use parameters, go to parameters and create the float parameter. Let's call it speed IT condition. Here you can set the condition that needs to be made to execute the transition. So go from idle to move. If the speed is greater than some small number, 0.01. Select the other transition change settings for the condition set speed to less than 0.01. If you try to play the game, still nothing happens. In the player controller script. In some way, we need to control the parameter speed. Create private void function, set any values. We also need to get animator component. I will call it enum. To set the parameter speed, we use that animator write any data set float. It's important to write the name of the parameter correct inside quotation marks. Then we choose a value for the parameter. And for that, we need velocity on the x-axis, but we need only positive numbers. So we use the absolute value function, right? Mate, F, that ebbs parenthesis, and we need RB, that velocity dot x, y. We use the absolute value function when the player moves to the left, velocity is negative and the animation will change for a move to either, because negative is less than 0.01. To avoid that, we use the absolute value function, which always returns a positive number. Negative numbers become positive and positive numbers stay positive. Now, we can move left and right and still be in the more animation. The last thing we need is to call the function in the update. Let's try it. Great. Check the reminder and see you in the next lesson. 15. Player Jump: Let's make the player jump. As you know, we have our bottom 40 jump. It's a Spacebar. First we need to get inputs. So go together. Input script, create parabolic bowl, jump input variable. Now we need two functions similar to the move functions. Create a jumpstart function and set the jump input to show that will be the function for the performed phase when we press the space bar, we also need the jump stop function. Set the jump input to false. The next step is to assign a date functions. The difference is that now we assign to the action Jump, not move. As I said before, performed, use Jump Start. For cancelled jump, stop. Also remove functions on disable. In the player controller script created the jump player function. And the truck. If a jump input is true. Instead of using double equals sign, we can use a short version without equal signs. If this is true, we enter the if statement. To jump. We said velocity to new vector two on the x-axis, we still want to move in here control while we use a jump. So we multiply value x with speed. But for the y-axis, we set jump force. Create float variable jump force. The last thing in the fixed update below demo function called the jump player a function. And just for safety, we can clear input just after we jump. In this case, we don't need to wait for the player to stop pressing the space bar. Set the jump force in the Inspector. I said the game window to maximize on play so you can see better. As you can see, I can jump about falling is too slow. Let's increase gravity and increase the jump force. It's a much better feeling right now. Of course, we don't want unlimited the jumps, so we need to detect the ground somehow n restrict the jump. This is material for the next lesson. See you in the next video. 16. Ground Detection: Before we start anything, we need Set Collision layers for the player and the ground. Create two layers, player and ground. Now assign the ground layer to the ground township. Select the player and choose the player layer. Next, go to the collision matrix. Let's set up our collision for the player and ground layer. Ground layer, you can disable all except the default end player. For the player disable all boxes. In that way, the player will collide, they just fit the ground and the ground can also collide with our default layer. Here is an idea of how to detect ground. We can check it by shooting an invisible array from the player speed. If the ray hits something below, it will detect the ground. If not, that means we are not on the ground. The first thing we need to do is to create a child object. This will be the point from which we shoot the ray. Place it on the bottom left side. Let's see how we need to set up things in the player controller script. First, we need some variables. Create public float, array length, then public layer mask, so we can set a layer for the ground. Then we need a transform point from which we shoot the ray. The list variable is bold grounded, so we can store information if we are on the ground. You can set a default value to true or false. Let's create another void function that will shoot arrays. Now, let's take a look at the syntax. First, we create the array case heat to the variable. Then we use physics 30, that array cast. With array kissed, we create a 1D array and store information in the re-cast heat to the variable. Now, we need to determine from which point we shoot the ray. That is a left point position. The next is the direction we need to shoot the ray below the player. So we write the vector 2 down, then array length. And what the layer we need to hit. That is the ground layer. If we hit the ground layer, then left the check heat will be true and we set grounded to true. Else we are not on the ground and we set the ground or variable to false. Then we need to add one more condition to the jump player function. We can jump only if we are on the ground. Don't forget to call the function in the fixed update. In Unity, we can set array length to some small number 0.05. Then select the ground layer for detecting ground. The position from which we should array will be child object left point. Remember this child objects move with the parent object and that is the player, in this case, press Play. Now the player can jump one time from the ground. If you came to jump and try to increase array length. However, to be precise with detecting the ground, we need to see the ray, but we can't right now for debt, we need to create another void function, C arrays that will take one parameter, re-cast heat to the idea is to see one color when the ray hits the ground and another color otherwise. So create one color, I will call it color one. Here is our little trick for the if statement. Instead of using the keyword if, we can use a question mark, right, left Check heat, question mark, then write the color you want. If the left Check heat is true for me, it will be red. Then write a colon and a color if left Check heat is false. So the ray will be red if the player is on the ground. If note the ray will be green, then we use the ball dot drought ray. We need to draw a ray from the left point position. Then vector 2 down multiplied with the right length. And the choose Color 1, which means red or green, depending on the state. Called the function inside the check status function and as argument, use a left check it. We are ready to try it. Press play, and go to the scene window. You can see the red array, which means it hits the ground. Let's change the array length. Now you can see that the red is green, which means it doesn't hit the ground. You can always play a guessing game and try to find the base array length. But it's much easier when you can see the ray. Of course, it's too short now, we needed to increase the length or move down the child object. This is my end result. Child RGB is a bit more down and the length is 0.02. Remember that unit, it doesn't save changes during play mode. After you exit the play mode, change the length to the best numbers for you. The next video is a challenge for you. Check the reminder before you continue. 17. Challenge+Review- Ground Detection: In this challenge, you'll need to create another array for detecting ground. The end result should look something like this. One array for each leg and the player should be considered on the ground. If just one or the race is touching the ground, it can be left or right. Take a moment to do the challenge and then continue this video and see the solution. The first thing we need to do is to create another transform point for the array. I call it a right point. Then we create another array cast kit to D and shoot the ray from the right point position. Then we change the if statement. Grounded will be true if one of the rays hits the ground. So left check hit or a write to check hit needs to be true. Also, you can adjust the C raise function so you can see both to raise, it's the same procedure. Just copy paste and change a few variables. Make another color and set the right point position and use the second color. Then we can go in Unity, select the player, and for the right pointer reference use another child object. And that's it. You can press Play and everything should work. See you in the next lesson. 18. Jump Animation with Blend Tree: In this lesson, I will show you how to make a jump animation for the player. Idea is to use a blend tree so we can merge separate animation states when the player jumps up and when he is forming. Notice how jumps sprites are different. Here you can see that the tail is down. This is for the animation when the player jumps up in here, the tail is pointed out. This is when the player is falling. The middle one is the transition. Sprite can make two or three animation states, but we can use blend tree to merge them in one animation state. First, we need to make an animation for each jump sprite. Create an animation for jump up. In the US, the first sprite from jump sprite sheet. Note that we are using just the first sprite. Then we need to make another animation jump, peak and use the middle sprite. The last animation is for jumping down. Use the last sprite. Now we can go to the animator and delete animation states because we will use the blend tree that will merge these states in one state. Right-click, Create and choose blend the tree. We can change the name to jump, then double-click to open it. You can see that we are now in the blend tree jump section in the basal layer. The next thing you can see is that the blend that type is 1D, which is good because we need just one dimension and that is vertical speed up and down. So let's create another parameter for vertical speed. I will call it a V speed. Now, we can use that parameter in the plane, that tree. To add animation clips to the blend tree, click on the plus button. We have three animation clips for the jump. So we need three motion fields. Go to the Animations folder and add the jump up clipped to the last place. Jump big for the middle. And jump down will be the first clip. The next thing we need is to set up thresholds. That means determined which vertical speed will trigger which animation. Disable automatic thresholds. For the jump down animation, we need a negative vertical speed, set it to a small negative number. For the jump peak, set it to 0. And for the jump up animation, we need a positive number because we are moving up and we have positive vertical speed, set it to 0.5. So depending on the vertical speed, we play corresponding animation. Go back to the basal layer. We need the option to transition from idol and move to the jump animation states. So instead of making the transition from each state, we make the transition from any state, no matter in what state VR, we can go to the Jumps state. Of course, we need to change settings and set conditions. If condition, we need one more parameter for the ground state. It will be a bowl parameter. The player will start with the jump animation if the grounded parameter is force. Take note that sometimes when you make a transition from any state that it can freeze and pledges the first frame of the animation. In that case, you would disable transition to sell. This happens because the animation makes a transition to self over and over the blend that tree. We don't have that problem. But later in the course, you will see some examples. To exit the animation, make the transition from jumped to either change settings and add the condition. Again. We go to idle animation. If the grounded parameter is true, then go to the player more control script. We need to set parameters in the animator value function, set the speed to velocity on y, and set the grounded parameter to the grounded variable. Now, we can try it. As you can see, when the player jumps up, we have one animation. When he's going down, we have another animation. And between we have jumped peak animation. Just to be sure and conditions to idle and transitions, we need to be sure that the player is on the ground to play those animations. And that's it. See you in the next lesson. 19. Double Jump and Additional Jumps: Let's create the double jump for the player. It's pretty simple. In the player move control script, we need a private bowl double jump variable. You can set a default value to true or false. Now in the player jump function, when we press the jump button and that the player is on the ground, we said double jump to true. Then we need an else if statement. If the taboo jump is true, do the jump. Then we set the value to false. Let's see a logic behind this. We are on the ground. We jump one time and enable double jump. When we are in the air, we press the jump button again. And because the double jump is true, we jump again and reset the double jump variable. The last thing we need is to set dabble jump to false when we are on the ground to reset the variable. We can try it in the urine. As you can see now the player can use double jump, but we are not done. I will show you another approach that is more flexible. We need to create public int, additional jumps. For example, if we need our triple jump, set it to additional jumps, then we need one private int, reset jumps number In the start function set, or reset jumps number to a default value of additional jumps. Then instead of checking for a double jump when we are in the air, we check if we have additional jumps. If the number is greater than 0, do the jump and decrease additional jumps by one. Also, don't forget to reset additional jumps to a default value when we touch the ground. And that's it. We can try it now. Great. We have a triple jump. Now you can set any number for additional jumps. For dabble jump, set the value to one. I will use the first approach because this is a simple project, but in your projects, in games, usually it's better to use the second approach, it's more flexible. See you in the next video. 20. Fix Sticky Walls: Maybe you noticed that the player sticks to the walls. Move the camera so we can see the left wall. Press play and go to the wall. Try to jump and hold the Move button for the left side. You can see how the player is stuck in the air. It's very easy to fix that. Create a folder for materials. Right-click, Create 2D physics material today. That will create physics material that we can edit to the player. First, we need to set friction to 0. Then select the player. In rigid body settings, you can see the material field. So direct materials sleep that we created. Now you can try it. Great, no more sticky walls. Also, notice that colliders also have a material field. So this will work either way. You can add material to the collider or rigid body. Quick Info, usually unity priority is to use materials from colliders, then from rigid body. Also, there is a possibility to set the default material for colliders in the Project Settings. Under Physics 2D, there is a field for default material. Click on it and choose slippery material if you want. This is it for this lesson, showed the remainder and see you soon. 21. Controller Setup: It's pretty simple to make controller inputs. That is why the new input system is great. Before we start, make sure you have the controller connected. Now go to Control-C input actions. First, let's add a button for the jump. Click on the plus button and edit the binding. Click on listen and press the button you want. You should see two options. One is button for all support the controllers, and the other is just for the Xbox controller because I use that controller. Now, if you use another controller, then you should see a specific button to that controller. I want to use all supported devices, not just the Xbox controller. So I choose the first option, save it. We can immediately tried, you don't have to change anything in the scripts. Great. I can jump using my controller. Let's add more controls to move the player with the controller. So it 1D Xist to the move action. Let's use the bed for this for negative binding, press the left button and you should see a bunch of options. First is just the pet. Bad debt includes all four directions. We need. Just deepened left direction. Again, you can see specific controls just for the controller you use. We need to support all controllers. So we use the general option D pet left for the positive binding, use the PID right? Before we tried, Let's add bindings for this thick. Create another one. Dx's. For the negative binding. Use the left stick, left direction. For positive, use, right direction. Save it. Go to play and try to use at the PET. As you can see, the pen will work great, but we have a small problem with the stick. The stick returns float values between minus 101, so we can move at different speeds. This is good if you want sensitive moment, but for the platformer games, you need precise instant reactions at the same speed. Before we changed something in the script to solve the problem, let's organize in protections. As you add actions and bindings, it can become a bit messy. So we use schemes, go to Add controller scheme, reuse schemes to group actions for certain devices, for example, keyboard and mouse. You can add a keyboard, a mouse to-do list. Also you can see requirements for devices. They are optional or required for a specific bindings to be active, I choose required. So we need a keyboard and mouse to use specific bindings. Save. Let's add another scheme for controllers. Same procedure, just pick gamepad. You can see that now we are in the controller scheme. Let's organize bindings. Space goes to the cable scheme. Button to the controller. Now assign other bindings. Because we are in the controller scheme, we can see bindings just for the controller. If we go to the caber scheme, we see bindings just for the keyboard. Of course, you can see all bindings just like before. If you choose all controller schemes, it's a nice way to organize input actions. Now, let's add a dead zone to the stick axis. Although we use the stick to move the actions thick Xs is one, dx is type. So we must use the x is dead zone. If you use the stick dead zone in this example, it will not work. Choose the x is the zone. Find the right number for you. I will just set it to 0.3. Save a set, and go to the gather input script to solve the problem with player movement. Let's use the bug value x, so we can see values in the console. Now you should see the problem in numbers. I'm using the stick to move and all these values are returned values that we use to move the player. We need them to be just minus 101. To do that, we use one function from mathematics, right? Met F and that round to int. And inside braces use ctx read value from inputs that will around the input to the nearest integer. For example, if we move the stick slightly, the input value is, let say 0.2, the function will return 0. Actually, every input between 0.50 will be 0, so we don't move slowly. With this approach, you get a slightly bigger desert, but you can compensate it with an X is dead zone in unity. However, if the input value is 0.5 or greater, the return value will be one. For negative, everything between minus 0.5 and minus one will become minus one. Let's try it. You can see that values are now just 0 minus 11 and we had the same constant speed. Of course, there is a different approach to this problem. If you want, you can make IF statements like this in the start move function, instead of using the round two int function, we can convert value x to one if the input is slightly over 0. If we are between 0 and minus one, set to the value two minus1 and else it's 0. With this approach, you don't have a small extra dead zone. It's up to you. I will use the round to infarction experiment and see what is best for your project. This is all for this lesson. See you in the next video. 22. More About Controllers- Avoid Mistakes: Let's take a look at more ways how we can use the new input system to move the player. You don't need to do this in the town. A platformer project. I just wanted to show you more about the input system and how you can use it in your future projects and games. So don't do this in the project right now. Just watch. First, let's delete the bindings for demo action. As you know, the value of the move action is set to any. So it can be any of the listed values. And usually you can't mix them because in the script you need to read the correct value. That is why I deleted x's bindings. Now, I will use the stick and vector two values. You can leave the value at any saw unity will automatically detect what we use. First, let's add a binding. Go to listen and move the left stick. Now, I will choose the first option, left stick, to get all four directions from the input. Save the acid and go to gather input script. Let's create some variables. We need vector 2 and another float variable for the y value. In the start more function for horizontal vector use ctx read value. And in this case we use a vector to, because the controller stick is considered as a vector to set the value of x to the x value from the vector, right horizontal that x from vector, we can also set the y axis value. So for the value y, use horizontal dot y. This is one of the ways how you can get the y-axis value. The platformer project, we will use a separate one. Dx is for the y-value to move on the letters. Here from the controller stick, we get both x and y-values. Don't forget to clear the y-value. Let's try it. Now we can move, but we have the same problem. We get float values between minus 111 of the solutions is to use the round two int function as we did before. Let's add the zone. There is one difference. Now you don't use the x is dead zone as before, you need to use a stick dead zone. Let's see another example. Although we can use the stick pain vector tutti under the same input action, less deleted and use a 2D vector composite. Now, we got four bindings for each direction. At default mode is digital normalized, which means that bindings behave like buttons. We get values minus 11. For the up binding, use a left stick up and so on. Press Play. Now you can see in the causal that values for the eggs are whole numbers. This is good. But if you hold the controller stick in diagonal position because of math calculations and normalization, you will get a float value of minus 0.7 or 0.7, and the player will move slower. Unity assumes the player needs to move in a diagonal direction. And this is a problem. Again, if you are making different games, this can be fine. But for a platformer, it's not a number that is talking about this. Again, we can solve it to be to the round two int function. Let's try it. Great. But there is a bedside to this approach. For example, x's and stick dead zones will not work. You can edit them, but there is no effect because we use a vector to. However, default, dead zones will change behavior. You can use them, but you can't have different deciles for horizontal and vertical movement. You need to find what is the best solution for your game. Now, we are ready to continue the tile map platformer project. See you soon. 23. How to upgrade Unity Version (Upgraded to 2020.3 LTS): In the middle of this course, long-term support came for the 2020 0.3 version. So I will switch to death version and show you how to upgrade your project. If you are using version above 20.320, it's fine. Pretty much every 2020 versions are good for this course. Go to instance, click on Add. I will choose the 2020 LTS version. Click on Done, and installation will start. I forgot to add modules, so I will edit them after the installation is complete. Go to edX modules, choose a Meno's and make modules. Again, waits for the installation to finish. Now go to projects, find tile map, 2D platformer, and then click on the Unity version, select 20.320 or newer. If you have, then click on the project to open it confirmed that you want to upgrade, make sure you make a backup before a wedge for the unity to do the job. And that's it. As you can see in the console. No errors. Everything went fine, simple and easy. See you in the next lesson. 24. Main Camera Info: Before we start with cinema machine, and let's take a look at the main camera. I will quickly show you with the most important details because later we use in change settings using cinema sheet. Let's see what we can do with to the camera. The most important information you should know about the camera is the size and pre-action type. Which size? Of course, we change the size of the camera. Increasing it will increase your view port and vice versa. For 2D games, we usually use an orthographic camera. Perspective camera is more for 3D games. Perspective camera, objects that are closer to the camera will be bigger and objects that are further away will be smaller. That is something that we usually don't need in 2D games. So we use the orthographic camera. Distance to the camera doesn't affect the size of objects, but still, you need to be careful about the z axis position of the camera in the game objects. If you go to 3D view, you can see the camera and objects in 3D space. Make sure that objects are in front of the camera like this, otherwise evil not see them. For example, I will change the z axis position of the player. Now, I can't see the player because he is behind the camera. So be careful and check the z. X is position of your objects. Press Control Z to undo the action. Also, we must use the orthographic camera because of the pixel perfect option that we use in the next license. And it works only with the orthographic camera. Let's see other options. Maybe something will be useful for your projects. We can choose whichever layer is the camera will render. Also, we can play with the background type and color. I use a solid color type, which is just the color you choose for empty space. You can see that we can change the empty space to any color we need. For example, I use color from the ground tile map. It will save you time so you don't need to place so many tiles around the ground. That's all for the camera options. We see more options where we import cinema. She see you in the next lesson. 25. Cinemachine Follow Camera: With seen a machine, we create the virtual cameras that can follow the player to use cinema machine, we need to go to the Package Manager in Unity Registry search cinema machine. I will install cinema screen version 2.6.4 at this time is the latest verified the version. Now you should see cinema machine in Unity editor. If you don't see it, probably you are using a newer version. So you need to right-click in the inspector and you will see Sina machine. As you can see, we have many different cameras that we can create. Of course, we need a 2D camera. This will create our virtual camera in the scene. Also on the main camera, Unity, we'll add the cinema machine brain component is the main part of the senior machine, and the virtual cameras need this brain to function. Let's select the week came 1. First, we need to set followed target. What this camera needs to follow. That is the player. Now you can see in the game we know red and blue zones with some lines. For now, we can disable those. Press play, and you will see that the camera follows the player. Of course, we can change the settings in behavior of the camera. Now, you don't change size on the main camera and the lens, you should see orthographic size. I will set it to five. Let's take a look at body section and options. Default to body type is a framing transpose can check other types, but I think that this has the best options. Then we can click on Save during play. This will save changes from the camera even in the play mode. And the first option is a look ahead. The time when the player moves, the camera will try to be ahead of the player. But you can see that the camera behaves a bit glitchy. You can use smoothing effect to improve behavior. However, this will not solve the problem completely. The camera is still jerky a bit. You will see it on your screen. I will show you a quick fix and what you need to change in the settings. But first, let's see more possibilities. Next is damping. We have a slider for each axis. Damping determines how responsible is the camera. In other words, how fast will follow the player if we increase X damping, you can see that the camera will slowly go to the position of the player. Sometimes it can be useful for the y axis when the player jumps, you can get a smoother effect. I will set it to 0.4 for the y axis. But you can see similar problems as in the look ahead option. Maybe you've received better with full screen. It looks glitchy. And fix that. Let's exit play mode and select the player and the rigid bodies settings. You should find interpolation in short, where it's interpolation is used to smooth camera moment and eliminate the jerky behavior. We have two options, interpolate and extrapolate. If you read the documentation, you will find out that interpellate the smoothing based on the previous frame and extrapolate on the next frame later, we can have some problems on the moving platform if we use interpellate. So choose the extrapolate option. Also by Unity documentation, you should change interpolation only on the player. Don't change interpolation for other objects. Now, you can use a look ahead and damping options as you like. You will not have jerky camera movements. And let's try it with interpolation. You can see it's way better and smooth with no jerky movements. Next, we choose the position of the camera in regard to the player. Maybe you have seen games very go just to the right, like Super Mario. Then you set a screen like this. For this game, Let's move the camera up so that player sees more up than down. Now the player is not in center position, but it's common for platformers to have that kind of setting. Next is the camera distance, which is actually zx is. Remember the previous lesson, just make sure that objects are in front of the camera. Then we have dead zones. For this, we need aligns from the beginning, enabled them. Let me just increase that zooms. The camera will not move until the player exits the dead zone, I can move, but the camera is not moving. When I go to the edge of the dead zone, the camera will start to move. I will use just the height, the zone for a better feeling when jumping it. The soft zone is more for 3D games. You can play with the settings, maybe try another body type, and so on. Just for the information on the main camera in cinema machine brain is one important setting. Its update method. It determines how the camera updates. The smart object is a default method. It will try to use the best update option for each object separately. Fixed update mode is when you move all objects in the fixed update. Later in the project, we move plate forms using the transform component. So we can't use that option because we will get jerky movements. Again. Also, when using fixed update, you need to disable interpolation. The smart tablet is usually the best option, but there is no rule to this. You need to try and see what is the best method for your project. Sometimes it can be a late update. Now you know Cinna machine basics. In the next video, we set up a pixel perfect camera, which is a must-have for pixel art games. 26. Pixel Perfect Camera: If you make pizza art games, a pixel perfect camera is amassed hair, the peaks are perfect camera will give you a nice even pixels. And Chris pill, OK, first, select the main camera and the pixel-perfect camera component. As you can see, first, you need to set pixels per unit. And if you remember, this is why it is important to use the same pixels per unit for all sprites. For this project, it's 16. Next, you can see reference resolution. Usually I leave it like this. You need some small resolution because it's pixel art. But it's important that we use 16 to 9 ratio if you target PC platforms, this default resolution is 16 to 9 ratio. You can search for resolutions and ratio values on the web, but we're not done yet. We need to select the virtual camera and add another extension. A senior machine pixel perfect extension. And that's everything unit. Now you have the pixel-perfect k-mer in your game. Great. If you see the lines between tiles, that is the common problem for tile map package. To fix that shaped the fixed lines between tiles license after the remainder. See you in the next lesson. 27. Fix Lines/Gaps Between Tiles: To fix lines between tiles, which is a common problem. We have a simple and easy solution and also it can improve the performance of your game. We need to create a sprite atlas. Sprite atlas is similar to a sprite sheet. It's made from many sprites, but it's not organized in a grid. Go to Create 2D sprite atlas. And of course, because we use a pixel art, we needed to change Filter Mode and compression. Now we are ready to add sprites to describe the atlas. It all sprites that videos in the tile map. Then click on peg preview. You can see how the sprite atlas looks. This we're also improved performance because it will reduce the number of, of a drought calls. Usually you get a Zhao call for each sprite. And now we have one sprite atlas. That is the first step. For the second step, we need to go to Project Settings, find the quality, and disable anti-aliasing. And that's it. The lines between tiles should disappear. Check the remainder and see you soon. 28. Camera Boundaries: To avoid situations like this where the camera goes too much to the left on the edges or the level we need to set camera boundaries. First, let's select the virtual camera and it another extension. We need senior machine confined there. As you can see, this confinement needs a bounding shape. So we need to create a new object with a polygon collider that we use as a bounding shape. It the polygon collider 2D component. Now click on Edit Collider and make boundaries. This polygon collider, we'll restrict camera edges. Edges will not move beyond collider edges. Then we check Is Trigger box. Of course we need this collider to collide in just a bit the camera and ignore other objects. Let's create another layer. I will call it ignore. The collision matrix, disable all collisions for the ignore layer. And use the polygon collider that we made as a bounding shape. Let's try it. Much better, simple and easy. See you in the next lesson. 29. Collect Gems using Tags + [Mini Challenge]: Let's create a collectible object. The goal is to create a gem object that will disappear when it collides with the player. Let's use one or the gems prides from the gym sprite sheet. You can't see the gym because of the layer order. Let's change that first. Move default to layer in front of background and middle ground. The next step is to add a collider. I will use the circle collider. Set this collider as Trigger. Now, here is one piece of information that people usually don't know. Unity will consider every game object to which a collider and with no rigid body is static. Also, Unity assumes that aesthetic body will not move, change, or be destroyed. If you destroy or change anything on the static body, unity will need to render all physics stuff in the scene. Again, it could lead to a performance job. Of course, we need to destroy it jumps. So to avoid this problem as a rigid body 2D SET body type two kinematic to eliminate forces. Then you can create a specific physics layer for the collectible objects, but you can also leave it on default layer. Just don't forget to enable the collision between the player and default layer. Next, let's create a script for the gem. Edit the script to the gym object. Because the collider is a trigger we use on the Trigger Enter to the function. We need to somehow recognize the player when he enters the trigger to detect the player in the if statement, we check if the collider that enters the trigger has a certain tag. We use compare tag function, right? Collision.com tag. Inside the function, we write a string tag that the object needs to have to enter IF statement, in this case is the player tag. What is at stake in New York City? Let's select the player game object. Here you will find the tag drop-down menu. You can see the player tag also. You can add custom takes for other objects. Select the player tag. It's important that you write the tech correctly in the compare tech function. So double-check all letters. If indeed an object has the tech player then destroyed this gem. Now you can try it. Great. But by just destroying James in the future, you can complicate the implementation of the sound. So I will show you a better way to do this. We can just disable sprite, renderer and collider. Also, instead of creating variables in getting components in the start or awake, which is the best way. I will show you a quick way to get components. Note that this way is more performance expensive. For PC. It shouldn't be a problem, but it's your choice. In real projects, I suggest the correct way. Now when the player touches the gym, it will disappear because we disable the sprite renderer and we also disabled the collider so we can't detect collision more than once. You can see that the gym object is still in the scene. That is what we needed. I will show you why in the next section. When we implement sound for the gym, your mini challenge is to make animations for the gym, something like this. And also you can make a prefab in place, some gems in the scene. See you in the next lesson. 30. Sound Basics: Before we add the sound to the game, and let's cover some fundamental information about Unity audio concept. On the graph, you can see components that we need to play sound. You can see audio source, which is the source of the sound. Audio source contains an audio clip that you want to play. Then the sound can go through mixers and filters, or it can go directly to the audio listener. How would the listener listens for the sounds? And then it will play them through speakers. In this project, we use a direct approach from source to audiology center. By default, audio listener is placed on the main camera. Note that you can have only one audio listener in the scene. Here is the table of supported formats. In this project, we use the MP3 format. So let's import the Sounds folder. It should be in your folder from the project setup lesson. I will just drag and drop the Sounds folder. And that's it. You can see sounds in the project. Now, we are ready to add sound to the gym in the next lesson. 31. Add Sound to Pick Up (Gem): To aid the sound, we need to select the gym and add audio source. Audio source has a property audio clip. Let's use the gym out there clip. You can see other options in our audio source by default to play on awake is enabled. That means that the sound will play as soon as we start the seed. Press play and you should hear the Gem sound. If you don't hear it, makes sure that the mute button is not enabled. Let's change some options. I will turn down the volume and increase pH, the change frequency. I like this sound with a higher pitch. Let's hear it now. Great. Now we need to disable the Play on awake option because we need to activate sound with the script. In the gym script, we need to get Component Audio Source and use the function play. In this way, the sound will play when the player enters the trigger. Let's try it. Great. Because we worked on the Prefab. Don't forget to override the changes for all gem instances. Note that we don't destroy the gym because we would also destroyed the audio source component and it wouldn't play the clip. And that's it. See you soon. 32. Challenge + Review- Background Music: This challenge is straightforward. You need to set up a beggar and music. It's pretty simple. Create an object for the music. Of course, we need the audio source component. Let's choose one of the music clips that we have. We need to start playing music as the scene starts. So leave a play on awake enabled. Also, we need music to loop. Let's turn down the volume a bit. Press play, and you should hear the music. It's nice relaxing music. We have a kit that jumps around n collects gems. And that's it. See you in the next lesson. 33. Canvas Setup: The purpose of this UI section is to create a gym display and learn basics about UI. To create your elements, Right-click on the inspector or click on the plus button. Find the UI. Here. You can see all UI elements that we can use from text, image, buttons and so on. We need an image. Now you should see the image in the center of the screen. By creating the image we created Canvas. Canvas is the parent object for all UI elements. We also created the event system. You need event system for buttons to function properly. In the Inspector, you can see our warning that we need to switch the input module to the new input system. Let's replace it later in the main menu section, we customize that module with our UI controls. For now, we can just use default ones. Let's select Canvas again. The first thing you need to do is to change Canvas Scaler options so that UI elements change size depending on the screen size. By default, you can see that I can change resolutions and the image will have the same size. In the canvas scaler, change scale mode to scale with screen size. Then set a reference resolution to some numbers that are 16 to 9 ratio. We also needed to scale height and width evenly, set it to 0.5. Again, pixels per unit for this project are 16. Now when I change the screen size, you can see that the image size will also change. Of course, don't forget, to enable the pixel perfect option for UI elements. And we are done with the canvas options. In the next lesson, we add sprite to the image and texts for Jim number. 34. Image and Text Setup: Let's see how to correctly setup images and the text. First, let's select the image and use gym sprite as a source image. Now you can see the gym in the middle of the screen. Let's go to the scene window. Move the gym to the upper right corner. So this is a classic mistake and I will tell you why in the play mode change sizes or the screen. And you will see that the distance between the gym and right corner is not the same. What happened? If you take a look at the screen, this is the center point and this is some image. The image is in the right position. But if you take a look at the bigger screen, the image is not in the right position. This is because by default, the anchors are in the middle of the screen. And that means that the distance between anchor points in the image is always the same. So on the bigger screen you get offset. The solution is quite simple. We need to change a anchor points to the upper right corner. And let's go to Anchor Presets. Choose the upper right corner. Now, if you change the screen size, the distance to the right corner will be always the same. Grade. The gym is a bit too big, so let's decrease height and width. Now, we are ready to add text. Right-click on the gym and create text. The text should be the chart object or the gym. Well, let's create some space for the text. Also, we set anchor points to the middle, right. Because the text is a child. Anchor points are relative to the gym, not the screen edges. This is how we ensure that the text is always to the right side of the gym. Let's change the size of the text area. Now we can play with text settings. We can change color and alignment. Next we can change the font. Let's import some font. You can use any font you want. I will use some pixel art font. Link to the download page is in your folder. Let's increase the font size. Also, let's change horizontal overflow. This option determines how the text should behave when it's too big for the text area. If that happens, make a few adjustments, and that should be good. In the next lesson, we write code to change the value of the text. 35. Display Gems Number: To display James, we need to create one script, I will call it player collectibles. Plays this script on the player. First we need one variable, a four digit number. Then we need a reference to the text. So we need to include the Unity engine UI namespace. Then we can use the text variable which I called text component. Let's create one private void function, update text. Inside, we need to use the text property from the text component. So we write the text component, that text. Then we need to set that takes to Jim number. However, we need to convert it from int to string with the function ToString. Now let's call the update text function in the start. In Unity, use texts that we have in the scene as a text component. For example, I can set the gym number 2, 5, press play. And you should see that number. Idea is to increase the gym number and update when the player collects gems. Let's create another function, this time public. In this function, Let's increase the number of jumps by one and then update text. This function needs to be called when the player collects gems, go to the gym script. When we entered the gym trigger, we need to get component player collectibles from the player and the code, the gem collected function. The gym number to 0. Let's try it. Great, everything works, but we are not done. I wanted to show you one of the tricky thing about this approach. Let's make our player prefab. Use the prefab in the scene. Notice how the prefer but doesn't have a reference to the text. So prefabs can't remember references from other objects only what is on the prefab itself can be remembered. In other words, in every level, you need to set up our reference to the prefab in the scene. It's perfectly fine if you choose that option, but it takes away some possibilities. A different approach is to add a tag. You can add the tag to the parent object jam in Canvas. In the script, you can set text component to private. In the start, we can find the display by writing gameObject that find objects with tag. Here we use the JMU I tag. This is how we find the gym object for display. Then if you remember, the text is the child object or the gym Soviet use the Get component in children function to get the text component. Just make sure that you find the text component before calling update text function. This is the correct order. So first you find the text component, then use it. We can try it now. No errors and you don't need too many or we setup our reference also makes sure that you have the gym display with the correct dig in every scene you use the player. Of course, there are more ways how to make a display for James and how to change code. You can experiment and use the best option for you. See you in the next lesson. 36. Health and Damage System: When creating our health and damage system, I like to separate it from everything else. So let's select the player and create a child object, call it a player stats. Let's add a collider that will be responsible for detecting enemy attacks. I will use a polygon collider. Polygon collider care precisely follow the shape of the player. Also, it's good to separate this collider from the capsule collider that we use to move on the ground because of functions like on collision enter and On Trigger Enter will be called for each collider on the player. If we put this polygon collider on the player directly, we may get calls from both colliders, polygon and capsule collider that we use for movement to avoid debt and other possible problems. We made a child object with a separate collider. It looks complicated, but it's a simple concept that gives you so much control. This collider needs to be a trigger. Now, let's create the layers to get more collision control. I will create a player state cell layer, but I will also add more layers that we need in the next license. And enemy attack and enemy layers go to layer collision matrix. The enemy needs to collide with the default and ground layers. I don't want a collision between the enemy and player, so they will not block each other. The enemy attack layer needs to collide just with the player state cell layer. Changed the layer two player stats. Then let's create a player stats script and of course, edit to the player stats child archea. We need some variables to store health. So create to float variables, makes health and health in the start. And let's set held to maximum health so that player has full held at the start. Then we can create one public function that can damage the player and decrease helped. It needs to have one parameter, damage inside the function v decrease held by damage amount. Then we can play hurt animation, which we do in the next lessons. Of course, we check if the health is less or equal to 0, then the player is that. Okay, let's see how this works. Idea is to call that function when enemies successfully attacked the player. Just for this example, we can call the take damage function in the start and damage the player with 20 damage in the inspector set maximum 100 and press play after the player takes the image, we expect held to be 80. Great. Of course we can kill the player if we set held to 10. You can see in the console the player is that an health is below 0. In this case, we need to disable player controls and disabled polygon collider so that we don't detect further collisions. First, let's disable the polygon collider 2D XAML controls. We need to go to the gather input script and create a public function that we can call in the player stats script. And we can just copy paste from the non-disabled function. Also, we clear input by setting value x to 0. In the player states script. We get component in parent because the gather input script is on the parent object. And then we call disable controls function. If you try it now, the player can't move and the polygon collider is disabled. This is the base of the health and damage system. Let's add more features in the next lesson. 37. Damage Prevention Time using Coroutines: To improve this concept, let's add damage prevention time. So when the player takes damage, it has a small recovery time in which is not possible to take the image. First, we need the bowl variable, can take the image and set a default value to true. Then inside that take the image function, we check if can take damage is true. Then we need to damage the player and do the rest. Now, we need to change, can take damage to false, and wait a small amount of time. This is a very use coroutines. Coroutines are functions that can delay the execution of code. The syntax is a bit weird. First, a Ve created the ID numerator function. Inside, we set the bowl variable to false, so weekend, take damage. Then we wait a small amount of time by writing yield, return new. And now we have options to wait for different things. For example, wait for end of frame, but we need to wait four seconds. I will set the wait time to 0.15 seconds. After that, we check if the player is still alive. If that is true, then set the bowl variable to true. So we can again take the image. We can play that animation. The last step inside the first if statement called the damage prevention function. To call IE numerator functions, we must write start Coubertin in, inside the parenthesis, right? The function you need to call. Okay, this is all we need. First, we check if we can take damage. If that is true, decrease health, check if we are alive, then we start coroutine. In coroutine, we set the bull variable to false, so we can't take the image. We wait for 0.15 seconds and then enable damage again. To demonstrate that called the take the image function one more time. Press play. And you will see that the player will take the image just one time because the second take damage function was called Inside the zero-point fifteen seconds. This is all for this lesson. See you soon. 38. Spikes: To create spikes, I will use this sword sprite. If you have a sprite for spikes, feel free to use it. I will show you how to use a mask for sprites to modify the sword and create something like this. So if you try to put as soda sprite in the scene, something strange will happen. You can't see the sprite, but unity created material from death sprite. This material is now used on the background tile map. So let's change the material back to surprise default. Also delete the material. An easy fix for this is to make the grid and selectable. Now, you can use a sword sprite. We need the spikes in front of the player, but the behind the ground. So let's create one sorting layer foreground. The next step is to hide the bottom part of the spike behind the ground. For that, we need a child object. Let's add a mask component. Make sure you add the sprite mask. For a sprite, you can use anything that has a square shape. Now you can see the shape of the mask. Move it down a little. The celiac, the spike, and go to my desk interaction. We need the sprite to be visible outside of the mask. Great. And let's add a rigid body 2D and change the type to kinematic. Next, add a polygon collider. I will delete the points of this collider, make adjustments. Select is triggered bulbs. Then set this to the enemy, a taker layer. We can change the layer just for the parent object. Then we can create the script spikes. Either the script to the spike object. First, we need the variable damage that will determine how much damage despite Q will do. Then we use the On Trigger Enter 2D function. Because the enemy attack layer collides Just a bit of the player state cell layer. We don't need to check if we hit the player. It's always the player. So we get the player stats component and cold the take the image function with the variable damage that we created. We can delete function calls from the players test script. Set the damage to 20. Let's try it. You can see that we take the image by touching the spike. Nice. If your enemy attack layer collides with other layers, then the player states, then you should create a tech ed States tag to the player states object. Then when detecting a collision, check for tag states. And you will be sure that the collided object is a player, so you can give component and due to damage. The last thing is to make a spike prefab. And that's it. See you in the next lesson. 39. Hurt and Damage Animations: In this video, we'll create two animations for the player. One is when the player takes the image and another when player dies. So first, we create hurt animation, use the white sprite. Next is death animation. Change sample rate to 15. Then in an emitter, we need to make transitions. The player can go to hurt animation from any state. To exit the animation, we transition to idle and of course, from hurt to death animation. Next, we need to bowl parameters. I changed conditions and settings for transitions. We go to the hurt animation. If the damage parameter is true and false. We exit the hurt animation. If the damage is false. And for death animation, the parameter needs to be true. But we also need to change the transition for the jump. Because if the player takes the image while jumping, jump animation and hurt animation would fight each other. The jump animation needs to play only if damage and death parameters are false. Remember that the player stats object is the child object or the player that has the animator component. Then we can go to the player stats script. We need to get the animator component from the parent object. If we take damage, a set parameter, damage to true to start the hurt animation. Then in the IEEE numerator function after 0.15 seconds, we stop hurt animation by setting the image to false. If health is 0 or below, then we set parameter that to true. Let's try it. You can see the hurt animation. If the player dies, you can see that animation. Okay, I forgot to disable loop time. Find animation and disable it. This is all we needed. See you in the next lesson. 40. Spikes Knockback: In this lesson, we'll learn how to make an Outback. To make an Outback from spikes. Let's go to the player MOOC control script. This script is responsible for all the moments and we need somehow to disable the move and jump functions when we start now back so that the player doesn't have control. Let's create a private bowl not Beck variable and set the value to false. Above move and jump functions. We check if the node package CHO, then return. That means that everything below this return will not be called because we don't call functions. We can't move or jump. Next, we need to apply forces to know peck the player. Let's create a coroutine function. Makes sure it's public because we call this in other scripts. It needs to take horizontal force, vertical force, duration, and transform position of a spike. First, ls determine in which direction we need to use knock BEC, left or a right for debt, we check if the position or the player on the x-axis is less than the position or the spike. If that is true, the player is on the left side of spikes. Numbers should be to the left. So set direction to minus1. Else we use now back to the right. Then we can set the bowl variable to true, so we don't call move in jump functions. Next, we reset forces on the player using vector to 0. Then we create another vector to that is the force of gnomic. For x-axes, use direction and force x for a while, use for swat. Finally, we add the force to the rigid body with the air the force function use the vector that we created and use the for smooth 2D impulse. Then we can determine the duration of the now MEK. Outer dead, stop the noun back by setting the value to false. And we again a reset the forces by setting velocity to 0. Now, we are ready to call this function from the spikes script. When we collide with the player, Let's get the player moves, controls component. Use get component in parent because spikes collide with the player stats, our object, which is a child object. Then we use a start Curtin and from the player moves, we call the non Beck function. Of course, we need to provide parameters. Let's create the variables for the force and the ration them to the function. For the transform component. Use the transform from this spike object. Just write a transform in the inspector and forces a and duration. I will make duration with hurt prevention time. Let's try it. Nice. You can change forces as you like. Let's do one more thing. We can also limit the player controls when we take damage. For debt, we need public bool has control, set it to true. The player has control a to the start. Then we can go to the player state script and get the component player controls. When we take the image, set has controlled to false. And don't forget to give back control to the player. The last thing we need to do is to add a condition. We came to move when no breakage to or we don't have control. And this is all for this lesson. 41. Health UI: Let's create our held by a Soviet can always see the health or the player. Of course, we needed to use the Unity UI system. So create UIImage. For the source image. You can use the Health Bar frame. As you can see, it doesn't look good because dimensions are off. To get original size, click on the set and native size button, it looks much better. Let's increase the scale a bit. We need this hailed Bar in the upper left corner. So go to the Anchor Presets and select the left corner. If you hold out, it would also change the position. Now when we have the right position, Let's add another image as a child object. For the image, use another sprite. This will be the background. Let's change the color to something dark. Then we create a child image of the background. This will be our actual held bar. You can again use the same sprite, set a native size, and change color to red. Okay, this setup is good, but I want to show you more possibilities of the UI system. So let's use this square sprites for the source image. Now, we don't see the frame, just the red rectangle. And let's change some settings to fix this. First, go to Anchor Presets, hold out and stretch this image. Then select the background and aid the mask. Now the hilt is a visible only inside the background space. That is why we again see the frame. Just make sure that health has enabled to change the hailed Bar. As we change health, we need to change the image type, set it to field. Now by changing the fill amount, we change the hailed Bar. The fill method is radial by default, but we need a horizontal mode. Now it's looking good. You can also change the fill origin from left to right if you needed. Idea, is to change the fill amount in the script when the player takes damage. The last thing, let's add a heart image. Change Anchor Preset to the middle left, increase the size. And I think that we are done with UI setup. Just don't forget to disable re-cast target for each image. You can see how it looks in the game, but if the player takes damage, nothing happens. We need to write some code to connect the hailed Bar and health go-to player stats script. First, we need to use Unity engine UI so we can get the image component, create one image variable, make it public. Then let's create a public update held function. This function will update the bar fill amount. So let's use a health UI field amount. Set this to the Health value. However, a fill amount uses values between 01, so we divide helped with maximum health. Note if you use health as an integer, then you should convert this to plot by writing float inside parenthesis. We use the float values, so we don't need it that this is all we need in this function. I call this function when the player takes the image. Also call it in the start function. In Unity, select the player stats are objects and for the health UI, use the image that we created. Let's try it. Great. The Health Bar is changing. Just remember the second approach to this is the same as in the gym display lesson. We can add a tag to the image. In the script, change the type to private, and find the image using the tail. And this is all for this lesson. See you in the next one. 42. Challenge + Review- Health Pick Up: In this challenge, you needed to make a health pickup. You can use the heart Sprite. When the player touches the heart, you should heal the player and update UI. Let's see the solution. This is the heart object. It has a kinematic rigid body 2D and circle trigger collider. It also has the script health pickup. In the script, we use the own Trigger Enter to the function. First, we check for the player tag. Then we can get the player stats component. To get player stats, videos get component in children. This is because the heart object is on the default layer and it collides with the player object. And of course, player is the parent of player states. So we must use good component in children. From player stats, we use the increase held function to heal the player for a heel amount. Then we destroy the heart object. You can modify this to disable the object and play a sound or whatever you need. Use the same concept as for disabling gems. Let's see the increase health function in the players that script. It's a simple public void function that takes one argument here. In the function, we increase the health by Hill amount and then check if maybe our health is greater than maximum helped. If that is true, set to maximum. This ensures that we can't have more than maximum health. Then we update UI. One quick tip. If you don't want to pick up a heart when you have full health, then you can add the if condition and check if the health is equal to maximum, then just a return and don't call increase health and destroy functions. In the inspector on the heart object set, he'll amount that we use in the function and that's it. I hope you all manage to solve this challenge and see you in the next lesson. 43. Enemy Concept with Parent and Child Classes: As you can see, I changed the scene and beat and edit one enemy. You can find a sprite files in the resource folder. For now, it has no functionality. It's just the game object with some components. It has a dynamic rigid body 2D and capsule collider. Let's change the layer to NMI. We can also create a special sorting layer for enemies. Set the sorting layer to enemy. We also have the animator. For now, it has one animation state, and this is a state for movement. It's not idle. You can see that the enemy has the animation. Now, we can start with parent, child classes and inheritance. Let's create two scripts. The first one is the enemy script, the second is patrolling enemy. In C Sharp, it's possible to inherit variables in functions from one class to another. We grew up the inheritance concept into two categories. Parent class, which is also called a base class, and child class, also known as derived class. The child class is a class that inherits from the parent class. To inherit from a class, you use the colon symbol. Let's see how we create child and the parent classes. Open the patrolling script by default, every class is a child class of mono behavior. After the colon replace motor behavior with the enemy class. In our example, the enemy would be parent class in the patrolling enemy is a child class. Why we use child and parent classes. Anyway, let's see this situation. If the enemy is the parent class, we can have child classes for every enemy type. Everything common to all enemy types needs to be either NME class. For example. Every enemy nice to have a health rigid body 2D animator and so on. Also, all enemies share similar behavior and use the same functions. Of course, we can have specific functions to the enemy type in the child class. But functions and variables that are used by all enemy types go in the parent class NMI. Then every child class can use those variables and functions via inheritance. For example, let's add public float variable held in the enemy class. Now a the patrolling enemy script to the enemy object. And you can see that this class inherited from the parent class enemy. To inherit the variables in functions, they must be public or protected. Protected is an access modifier that we didn't mention yet. It's something between private and public. You can't see protected variables in the inspector just as private variables. Also other classes, except child classes, can't see or use protected variables. So you can see a news protected variables and functions just inside the parent and child classes. We know that all enemies need to have a rigid body and an emitter. So in the enemy class, it protected variables. We can get components in the awake function. Now, you can use the rigid body in the child class, patrolling enemy. You can see that we can move the patrolling enemy. This is a great concept and this is how you should approach when creating enemies. It's easy to create other child classes for different types of enemies. In this project, videos, just patrolling NME. So let's go to the next lesson to add functionality. 44. Move Enemy: Idea is to make a patrolling enemy that will detect the age of the ground and change direction how certain the enemy needs to detect a wall in front of him and turn around. We can shoot a race similar when detecting ground for the player. But I will show you another way. We create two child objects. One child object will create a small circle in front of the player. And if the wall is inside that circle, we change direction. Another charged object will create a circle below the player. And if there is no ground inside the circle, then we are on the edge and we need to change direction. In the patrolling enemy script, create variables that we need. We need the speed and direction to move. Set direction to minus one because the enemy by default is looking to the left. Then we need to transform points for child objects and a layer mask for the ground. Also create two bull variables to store information. Create a radius for the circle. In the fixed update mood enemy with direction and speed variables. Then we need to create a function that will detect a waltz and edges and change direction. We store more information in the detected ground to create a circle that will check for the ground, we use a physics 2D that overlap circle inside. We choose the center of the circle, which is the ground check position. Then set the radius for the circle. The last thing, we decide each layer we need to check. This will return true or false depending on the ground inside or outside of the circle. If there is ground inside the circle, it will be true. If not, it will be false. For detecting walls. Do the same, just the change position to the wall check. Then we check if inside the circle we detected a wall or we didn't detect ground below. Then multiply direction with minus1 to turn around the enemy. Outer dead, flip the sprite of the enemy using transform local scale. On the x-axis, set the local scale to the opposite value with a minus sign. At this point, this is everything we need. But let's just create one function on Zhao gizmos to see the circles that we create, right? Gizmos dot Java virus fear. Then use the ground check position and radius. For a wall. Of course, the vault check position. Don't forget to call the Flip function inside the fixed update. In Unity, you will maybe see some errors, but that's because the own Zhao gizmos function doesn't have a reference for child object positions. Let's create two objects. One is for ground check and another form all checking. One needs to be in front of the enemy. The second also needs to be in front, butt on the ground level. Setup correctly referenced in the patrolling enemy script. We need to detect the ground layer set radius, and you will see small circles. So when this circle doesn't touch the ground, flip the enemy. When this circle touches the wall, also flip the enemy. Let's increase the size a bit. Set health, although weekend damage the enemy just yet. And setSpeed. That's it. The enemy is ready to patrol. In the next lesson, we damage the player when we touch spikes on the shield. 45. Enemy Attack: In this lesson, we create an enemy attack with the notebook option. To create an attack, let's create a child object attack that will have a polygon collider. We can edit the collider to make shield the spikes. Change the layer two enemy attack. Don't forget that the enemy attack layer collides, adjust the width of the player states layer. In the previous lesson, we created two classes for patrolling enemy, one parent and the child class. Let's do the same afforded attack. Create one script, enemy attack, and one script patrolling. A tech. Opened them. Patrolling attack, it needs to be a child of enemy attack. We again use the same concept. Every attack type will deal damage to the player, so that function needs to be in the parent class. Then we can add specific features, two different attack types. Now let's go to the parent class to create a function that will damage the player. Of course, we need a flow to damage variable. Then let's create our protected the player states variable that we can use in child classes. Use on Trigger Enter to the function to detect collisions. First, we check if the attack collided with players states that have the tag states. Then we can get a component from the collision. Then called the damage function from player states. Let's see how this works. The child class patrolling enemy total attack object. Set the image value. I forgot to set this collider to trigger. Then press Play. You can see that we take the image when the player touches shale spikes. This is the first part. Now we need to implement non-bank. Not every attack type needs to knock back the player. We need this option to some types of attack. For example, patrolling attack. To implement different behaviors in charge. The client says, We use a virtual function. It needs to be in the parent class. Let's create one public virtual void function. It's virtual because we can override it in child classes, leave the function empty and call it when the player takes the image. Now in the child class, let's override the special attack function by writing public override. You will notice that these function calls based spatial attack. The line of code we'll call everything in the base virtual function, and death is in the parent class. The virtual function is empty with no code, so we don't really need to call anything from here. You can delete a base call. But if you ever need something from the virtual function, this is how you call it. We can now add the functionality that is unique to this overwrite only. We need to call the numbered function. If you remember, the notebook function is in the player MOOC controls script. So let's create the player more variable. Somehow, we need to get component. Remember in the hierarchy we have child player states and the parent object player that has moved controls script. We already got the component player states in the enemy attack class. So we can use player states to get component, player Moon controls, use gate component in parent. Now, we can start coroutine and use a player move to call the notebook function. Of course, we need to provide arguments for the function, create forces and duration of float variables. This attack script is on the child object of the enemy, and we need the transform position of the parent NME. So we use transform dot parent for a reference. That means that we are checking if the player is a left or right in comparison to the NMI, so we get the correct direction. This is all we need in Unity, set variable values. Let's try. Great. If you want, you can change the attack collider and cover the entire enemy. Now the player should avoid the entire enemy, not just the spikes. This concept with parent and the child classes with virtual functions gives you great options to scale this project in your games. See you in the next lesson. 46. Change Levels/Scenes: To change your levels, I created this door prefab. It has the door script, kinematic, rigid body and trigger Box Collider. Idea is to load a new level when the player enters the trigger. First, we need to create another level. Go to the Scenes folder, make sure that you save this scene, press Control S. Then you can rename this sample scene to level one. Then press Control D to duplicate the scene. You can call this Main Menu. Later in the course, we make the main menu, but for now we need another scene. Call it a level 2. Let's make some changes in the second level so we can see the difference from the first. And this is what I made with tile map. And go back to the first level. Now, we need to include new Laos in the final build of the game. Go to File, Build Settings to add a scene in which we are now click on the edX open scenes button to add other scenes. Just a drag them. In this area. You will notice that every scene has a number. This is the built index number which we use to navigate through scenes. When you open the game, it will first allowed the scene with index 0. So let's move Main Menu to the top of the list. Now, a level one has index number 1 and the second level has a number two. We can now go to the door script. First, we need to include namespace, senior management. Then create one public int variable level to load. Let's create the function alone. The level inside we write a scene manager dot allowed seed. Inside parenthesis, we choose the build index or the scene that we want to load. For example, the main menu has a built in index 0. To make it changeable, we pass the variable level too loud. Then we need to choose a went to call this function. Of course, we call it when the player enters trigger on the door. In the Inspector, we need index number 2. Let's try it. When the player enters the trigger, we instantly go to the next level. In ideal cases, you want to create a fade in and out effect, which we do in the next lesson. But we still have work to do here to ensure that you don't call the load level function multiple times. And let's disable the door collider. Also, let's disable the player controls. This is one way of changing the levels. You can also change Laos using strings. So create one public String variable. You use it instead of int variable. In the inspector. Just make sure that you type correctly the name or the level you want to load. In this case, right? A level two. You can try it. Great. In this project, I will use the build index approach. The last thing, if you need to restart the level, create another function. Also use a scene manager allowed, see inside parenthesis it you need to get active, seen, build index. And that's it. Now you know the basics about senior management. In the next video, we improve this and make the fade effect. 47. Fade Between Scenes: In this lesson, we'll create a fade effect. First, I will delete some functions and variables from the door script. We will created them in another square root. You can leave the own trigger function and a level too loud variable. Let's duplicate Canvas. Yes, you can have multiple canvases in the scene. Delete the child objects, Create UI Image and call it failure. Now we can change the color to black. To stretch the image to full screen. Go to Anchor Presets, hold the Shift and Alt, and click on the stretch button. You can see that some elements from another canvas are in front. We need to change the sort order of the canvas. Increase it. Great. Now to the fader, add the canvas group component. Here we have our pestis control for performance reasons, it's better to control opacity from the canvas group then from the color property. In this way, we don't get a Joe calls when the value is 0. This black image is not interactable and also disabled block ray casts and re-cast target. If you don't disable those, recasting for the UI elements will be blocked and you can't press buttons that you can have. For example, in the pose menu. Idea is to change opacity with animations. So go to the Animation Window and create animation for the fader. Call it fade in. You click on the Record button and go to the 1 second on the timeline. Here, set it to 0. Now we have a nice fading effect. Let's try it. You can see that the animation is in the loop state. We need to disable it. Great. Next, let's create fade out animation. Click on the Record button again for the start of the animation, set capacity to 0. After 1 second, set it to one. We have a nice fade out animation. Also disable the loop time option. We need to connect those animations. Go to the animator. When we need to load the next level, we need to start to fade out animation, create a transition from trading to fade out. We need one trigger parameter, fade. This parameter will be a condition afforded transition. Next, I created this fader script. Let's edit to the fader object. First, we need to get animator component. Then we need one private int, a level to load Variable. Create one public function, set a level that takes one argument. This function we call in other scripts, for example, the door script. We set a level too loud to the level that we pass through the function when we call it, then start the fade out animation. In this function, we don't actually allowed a level. We just set the number of levels too loud and start the animation. We need a public function to load level. O course, we need at the scene management and namespace. Here we use the load seen a function for the build index. Use the level to load variable that we set it through the set level function. Now, go to the door script. We need a public fader variable. Afford the reference. When the player enters the trigger called the set level of function from the fader. Here we choose what level we need to load. Use the public variable level to load. Select the door object in the inspector for the fader reference during the fader from the fader Canvas. The level to load needs to be two. When the player enters the trigger, we start animation, but nothing happens. That is because we just set the level number. We need to call the load level of function when animation is finished, which means when the screen is completely black, select the fader and go to the fade out animation. Go to the last frame. And here we use animation event. You can see it here. Animation events can call public functions from the scripts at the specific frame. The only condition is that the animator and the script are on the same game object. This is important. We need to call the allowed level function from the fader script go to function. And you can see functions from other components on the fader object. Usually custom functions are on the bottom. Find allowed level function. Let's try it. As you can see, we can change Laos with Fade Effects. But in the second level, we don't have a fader that will create the fade-in, fade-out effect. So let's create a prefab from fader Canvas. You need to add debt prefab to every level. Plays the prefab in the second level. And don't forget to assign that prefer to the door in the second level. Let's see it. Now, we have a fade effect in both layers. Quick tip in the scene view, the fader can cover your screen. To solve this, we can use the Hide button in the hierarchy. The last thing I will show you how to implement the restart function with a small delay. In the fader script, we need two functions, one private that will set the level number 2, the active seen build index. Then we need one public function that we call in other scripts. Inside we write invoke. With invoke, we can call other functions and also a delay. We need to call a function or restart, write the name as a string, then write delay time. So when we call the restart level of function, we actually call the restart function after 1.5 seconds. Usually, we restart the level when the player dies, or we have a button to restart the game. But just to show you, I will call it in the door script. When we go to the door, we weighed 1.5 seconds and we restart the level. Now, we're stuck forever in one level, not a fun game. That's all for this lesson. The next lesson is one of the most important lessons we make. Game Manager. 48. Game Manager Setup: Idea is to make the script that will control the main game logic. For example, we have many objects that must communicate with each other, use functions from other scripts and that kind of stuff. The stepping stone can be connecting all these objects to function together. A lot of public variables, getting components and so on. Our goal is to create one and Game Manager, and that will have access and control to all necessary functions so that objects don't need to be connected directly. Everything is controlled with one script. Let's create one gameObject and the script Game Manager. For some reason, the script with the naming game manager gets these different icon. Is the script to the game manager object. Open it because we need just one game manager in every scene. Idea is to move this game manager from level to level. What happens when you go from level one to level two? All objects from level one are destroyed. And then unity creates all our objects for level two. So r objects from level one and level two are not the same. Objects. Create awake function to keep this game manager object and prevent this showing US don't destroy onload function inside parenthesis, right? Gameobject. This means that we don't destroy it, this game object when loading a new level. If you start playing the game, you can see all GameObjects from level 1 except the game manager. The game manager is in the spatial, don't destroy on load. Seen. Go to the next level. Here you can see objects from level two, and you can see that we still have the game manager. Great. Of course, the player sometimes can start the game from the second level or any other level, depending on the same system. That means that the game manager object needs to be in every level, create a prefab, and place it in a level two. So now when I go from level one to level two, we have two gay managers. One of them each level. Somehow we need to keep just one game manager and destroyed the second one. For that, we use to thing's static variables and Singleton pattern. Create one game manager instance by writing private static game manager. With keyword static, we save this instance in the memory and it will stay there until we exit the game. That's why we need to be careful when using it, but we also get easy access to this class. In other scripts. We don't need to find the game manager object and use getc component. You will see what I mean in a moment. Singleton pattern means that it can be only one end game manager. So we check if the instance GM is. Now. If that is true, we need to assign GM to this game manager script. You can place don't destroy, onload inside the if statement. If we already have GM assigned, then destroyed this game manager object. Let's try it. We start in a level one. At the start, GM was now. So we assigned GM to this game manager from the first level. We go to level 2. As you can see, we have just one game manager. This game manager is from level 1. The game manager from level to destroy itself. It checked for GM, but it wasn't. Now GM from the first level was detected. So we go to the else statement and there is just destroy function. Back to the script. And let's say we wish to control functions for changing levels. The functions that we need are on the fader object. Instead of gay manager searching for objects in the scene, in this case a fader, we can create static functions that will enable objects to register themselves to the game manager. Create public static, void, register fader, which has one parameter, fader. For safety, we check if GM is now, then return and do nothing. If we have g m, then set fader on the game manager by variety in G M dot fader to the fader, f, d. Now we can go to the fader script. In the start function, this fader will register itself because we have a static instance and functions, we have easy access and we don't need to find the game manager object. Just a right game manager that register a fader. And we use this fader as the argument for the function, right? This inside parenthesis, fader is now registered and game manager can use it. Go back to the game manager script. Now, we can use the fader and its functions. Create one public static function to load the levels. Now, we can call the fader from GM by writing GM, that fader. And we call the set level function. Go to the door script instead of calling the fader, called the Game Manager load level of function. You can see we can go in any script and call anything we need from the game manager. Of course, now you can delete the reference to fader. You don't need it. And that is the advantage of the Game Manager concept. Great, to prevent possible errors. You can also check for GM. Let's call the wrist our function. When the player dies, this function will call the restart function from the fader. And just to remind you, this is the function that we are calling. Go to the player stats script. And when the player health is below 0, called the Game Manager restart function. Note that there is no direct connection between the fader and the player stats. That is why we are doing this. And let's destroy it. The player. After 1.5 seconds, we restart the level, and that is the basic concept of the game manager. In the next lesson, we explore more possibilities. 49. Unlock Doors with Game Manager: In this lesson, we'll lock the door and unlock it when the player collects all gems. Of course, we use the game manager to implement the logic behind this. First, lights along the door, change the sprite in the sprite renderer. Then we need to disable the collider so we don't detect collision. I will change the size a bit and disable it. Go to the door script. Here, we need to create a function that will unlock the door. We need one variable sprite for the open-door. Then create public function, unlocked door. In the function changes the sprite to unlocked. Sprite, then enable the collider to detect collision. As you can see now, we are getting the box collider component twice and two, slightly improved performance. We can use variable and get component in the start function. Great. In the game manager, we need a function that we use for the door registration, create public aesthetic registered or same as before. In the door script called the function. In the inspector for unlocked door sprite, use the open gate and don't forget to override it changes. That's it for the door. Now, we need a system for detecting gems and checking if the player collected all of them, the number of gems in Laos is not the same. In one level. You can have more in another, less, and so on. The idea is to put all gems in one variable. Usually we used arrays, but as I said, the number of gems is not the same for every level. We can't change the size of the array. Once it's created, we must use a list. With the list, we also store a collection of objects of the same type in one variable, but the list is dynamic. We can add and remove elements from the list and change the size at runtime. To define a list, use the keyword list, then angle brackets in which we write the type of the variables we need to store. In this case, we stored the gym type variables, then write the name of the list. Here we just defined the list to actually create it, we can go to the awake function. For the list gems. You use the keyword new, a list of gems in parenthesis. After. Now, we can create a static function that will register gems and added them to the list. To add a gem tones analyst, we use a function that is available for lists, and that is the function eighth, write the name of the list that add a gem. For safety, we can check if we already edit that jumped to the list. Use the exclamation mark for negation. In function contains. We are saying if the list doesn't contain the gym, then edit. Let's create another aesthetic function to remove gems from the list. Idea is to call this function when the player collect the gym. Use a function remove to remove the gem from the list. Then we can check the number of elements in the list. If we don't have any gem in the list, the player collected all of them. Then unlock the door. Go to the gym script. In the start function, use the register gem from the game manager. In that way, every Jim will aid itself to the list of gems. And when the gem collides with the player, we remove the gem from the list and check if that is the last one. We can try it with. One gym. Go to the door, nothing happens. Collect the gym and the door opens. You can add any number of gems, and it will work the same way. And let's try with two gems. We need to do one more thing when we restart the game, which means that the player didn't collect all gems. So we need to clear the list, use function clear to empty the list. And that's it. With this approach, possibilities are endless. You can register our Health Bar and then control it from Game Manager. In that way, you don't need to add tags to the Health Bar and connected to the player, I will not do it now, this is just an idea of how you can use it in your projects. That's all for today manager. See you in the next lesson. 50. PlayerPrefs Syntax: To show you how to save and load data, I will first show you the syntax. You don't need to create this script in your project. It's just an empty script with one variable health. To save and load data, we use a player prefs. When you need to save data, right? Player prefs that set. And as you can see, you can save three types. Float, int and a string. Health is a float variable, so we use set float inside parentheses. First, we write a string key that will hold the value that we need to save. You can type whatever you want. I will call it healthy. Then you add value to that key. You can write a specific value or you can use the health variable. When you need to load the health variable, you need to get the health key. So right, player prefs that get. Also, you can get three types. We need a float type, make sure that you write correctly the string key, in this case, health key. After the health key, you can add some default value for that key. Because if you try to get a key that doesn't exist, you will get an error. Of course, when you get the value from the key, you need to store it in a variable that you need. In this case, helped. Let's check other possibilities. Sometimes you can check in the if statement, if some key exists, use function has key and write the string key. You need to check. Then you can do whatever you need. We also have the option to delete a specific key with the function delete key. Of course, you can also delete all keys using delete all. Note that you can use the public string variable as a key. In that way, you can easily change the key from the inspector. You can also delete all keys from the Unity editor that is super-useful when testing the game and the sale system. Go to Edit and find clear all player prefs. Now when you know the syntax and let's use it in the next lesson to save the health of the player. 51. Save and Load Health: With player prefs, we can save data when the player exits the game and we can load the data when we play the game again, how we can save and load the data between a levels. In this lesson, we need to save and load the health when the player changes levels. For example, if the player takes damage in one level, then we need to save that health value for the next level. Go to the door script. When the player enters the trigger, we need to save your health. And for debt, we need to set up a reference to player states to get the health variable. Then we can use the set float function to say helped in the health key. Use a player stats that health as value. Then go through the player stats script. Here in the start function, we don't set Health to maximum. We need to get a health key value. Use player prefs, getFloat. If we don't have that key, that would be the case when we start the game from the first level, then the default value should be maximum health. Let's try it now. Take some damage, glow to the next level. And you can see that the helper has the correct value. Let's exit play mode. If the player enters the game, again, you can see the same health value. I will show you how to change that. But first, let's kill the player. We restart the level and we don't have a full health. To fix this, you need to go in there prior stats script, when the player dies, set the health to the maximum health. Let's try it. As you can see, we have full health. Great. To reset the health value when the player exits the game, you can use the application quit function. This function is called when the pirate exits the game. Depending on the behavior that you want, you can save the health here. So when you play the game again, you will have the list Saved Health value. Maybe you want to set the health key to the maximum value or you can delete it. I will delete the key. If you choose this approach. Note that you also need to delete this key when the player goes to the main menu from the level. We don't have that option now, this is something that you do from the pose may knew more about it later in the course. Let's see what we did. Take some damage. Exit, the game, start again. And we have a full health. Great. It all depends on what kind of game you are trying to make. You can say whatever you need, maybe delays the plate. A level may be number of collected gems and so on. See you in the next lesson. 52. Challenge- Save Gems: In this challenge, you need to create a save and load the system for the gems idea is to save James when the player collects all of them in one level, I will not give you the solution this time material, get a quick tip. You can save the gym number in the door script. Don't forget that number of gems is variable in the collectible script that is on the player. Also, don't forget to load the gym number in the start function. If you have any problems, you can always message me or anyone under this cursor over. Good luck and see you in the next lesson. 53. Challenge Review- Save Gems: After some feedback from you guys, I decided to make a solution for the safe gems challenge for you that didn't manage to solve it. No worries, Let's do it together. The idea is to say gems, when the player collects all of them in, gets to the door. So in the door script inside the own Trigger Enter to the function. We need to get the player collectibles component so we can get access to the gym number. Remember, player collectables is the script on the player. Then we use player prefs to save a number. The next step is to go to the player collectible script. In the start function, we need to load a gem number and don't forget to set a default value. Let's try it. We have 0 Gems, pick one and go to the door. In this case, we go back to the same level. You can see that we have one gem. You can repeat the process. And now we have two gems. Of course, usually the door leads you to another level and that's it. See you in the next lesson. 54. Moving Platforms: In this lesson, we'll learn how to create a moving platform that we can move left and right or up and down. First, let's create an object to the, to the bookshelf sprite, rename it to platform. Then we did a parent object for this platform. I will call IT platform parent. Let's reset that the position of the parent and the child plate bar. Then move the parent objects so we can see we need at least to transform points so that the platform can move between them. Create one empty chair, the object, I will call it 0 and select the icon so we can see it. The idea is that the platform moves to that point. I will move the point to the left, then duplicate it, call it 0.1, and move it to the right. Now, we can select the platform and a rigid body to the change of body type two, kinematic. Next, we need a collider. You can add any collider. I will use the edge collider. It's just the straight line on the edge. Let's change the size a bit. O course, the platform needs to be detected as ground, so changed the layer to ground. For the start, this is all we need. We can create a moving platform script and edit to the platform. First, we need speed for the platform and then the array of transformed points. Remember, the platform should move between the transformed points. Until now, we only used the rigid body component in the scripts to move objects. We know that we must use fixed our blood when using a rigid body in scripts. But there is another way to move objects, which is perfect for moving platforms. We use the transform component. And because we don't use the rigid body component in the script, we can use the update function instead of fixed update to move the platform in the update, we write and transform that position to move with the transform component, we can use a built-in function by writing vector to move towards. First, you write the transform of the object you need to move, that is the platform. So we just write the transform position. Then we write it the position where the platform needs to move. It needs to move to wall off the transform points. So bright points, because it's an array, we must choose which point. For example, let's move to the point with index number 1. Then you choose speed. And because we are in the update, we must multiply the speed with time, that delta time. This is the time between frames and it's used to make the movement smooth. And even. In the inspector set speed. For the points array, use 0.01. Note that you can have as many points as you need. Let's try it. The platform moved to the point with index one. Now, when we can move the platform, we just need to change the point in the x's in the script creates the int variable for the index number. We need to move the plate firm to death index. So replace index one with I. Two change indexes at runtime. First, we must check if the platform is in the correct position. We use the vector to the stance to check the distance between the platform and the point position with index i. If that distance is less than a really small number, increase the index so that the platform can start to move to the next point. If the platform already was on the last point position, we need to set the index to 0. So we check if I is equal to the array length. Then reset the index. Let's try it. Great. I will increase speed a bit. Let's say that the platform needs to start moving from one of the points and not from the middle position like this. We can make one public variable that we use for starting index. In the start function, set the position or the private firm to the position of array point with index starting point. Now in the Inspector, you can choose a starting point. If you need the platform to start from the left, 0 is the correct number to start from the right, use starting 0.1. Let's try to get value one. As you can see, the platform started from the right. For value 0, it starts from the left. Nice. Let's make a platform debt will move up and down. We can create a prefab for this platform. Then you can move points. You don't need to change anything in the script. Press Play. It works great. You can make a prefab for the vertical platform. Change the name. Because you are trying to make a prefab from another prefab. You get this pop-out window. If you don't know what our prefab originals and invariants, I encourage you to investigate and read the documentation. In this case, I will select original, but it can be also used as a variant. We are not done yet because of the small problem that you might not expect. I will use the horizontal plates form of 46 example. If you jump on the platform and the player will not move. This is the material for the next lesson. See you soon. 55. Move Player with Platform: In this lesson, we'll learn how to move the player with platforms. Go to the moving platform script. First, let's detect collision between the player and the platform using the on collision enter 2D function. Of course, we need to check for the tech player. If the player, then we set the platform as a parent object using the set parent function. So the Platform will become the parent object for the player when they collide. Let's try it. You can see that the player moves with the platform and in the hierarchy, you can see the player as a child object. However, if we jump off the platform, the player is still a child object and it moves just like the platform. To solve this, we need to use the on collision exit 2D function. You can check if that is the player or you can skip that part. Here. We unparalleled the player by setting the parent to now. So when the player exits the collision, the platform will not be the parent. Jump on the platform. We mole, jump off the platform and the player doesn't move. You can see in the hierarchy that the player is not a child object anymore. Pretty simple solution. See you in the next lesson. 56. Platform Upgrade: This is a quick update on how to upgrade your moving platforms. For example, this is a situation when the player can touch the pipe from, from the side. You can notice the problem. The player becomes a child of the platform and starts to move. There is an easy fix for that. Go to the moving platform script. We need another condition. Check if the position of the plague form on the y-axis is less than the player position on y axis. In that way, we make sure that the platform is below the player. Let's try it. Great, it works, but there is one hidden problem. Let's move the platform a bit down. Let's see. Again the same problem. The reason is that the y position of the player is calculated from the pivot point. If you remember, when we sliced sprites, the pivot point was in the center of the sprite. So this is a reference point for the y position of the player. As you can see, the platform is below that point and this can make problems. One solution is to change the pivot point to the bottom. Another solution that I will use is to subtract this value. Go to the moving platform script. From the player position, I will subtract 0.7 or 0.8. This number will depend on the size of your sprite in your game. So it will be different for all of you. You need to find the correct numbers and also make sure that everything works fine on vertical platforms. That's it for this lesson. See you in the next one. 57. One Way Platform: In this lesson, we'll create our one-way platform so that the player can jump on it from below to create one-way platforms, I will use the same sprite as for moving platforms. Usually they need to look different, but this is just for functionality. This platform also has h collider 2D and it's on the ground layer. Since I'm not planning to move Huawei platforms, I didn't add the Rigid Body 2D component to make one-way platforms, we need to add platform effector 2D. Since we are using a factor for collider enable used by effector. Factor settings. Make sure that you use one way is enabled. That option will give you the surface arc that you can see. Everything below the arc will not create a collision. That's why we can jump through the platform or from below. Everything from above, we'll create a collision. That's why we can stand on the platform. Let's say How it works. Great. You can create the opposite situation by changing their rotation of sets to 180. Now, we can't jump through the platform because of collision detection, but we can fall through, Let's try it. I can't jump from below, but I can fall through the platform. You can also change the surface angle if you need it for some reason. Note that you can customize what will collide with the one-way platform using the collider mask option. These settings override global settings from the collision matrix. For example, you can set that this platform collides only with the player. That's it, very simple and easy to do. See you in the next lesson. 58. Player Melee Attack: In this lesson, we'll learn how to create a melee attacks for the player and how to deal damage to enemies. First, we need to add the action etag. Action type is button. Then assigned bindings. I will use the left mouse button, and I also added one button for gamepads. Select the player and go to the gather input script. Here, I created one bowl variable, try a tag. It will be true if we are pressing buttons and trying to attack or false. Otherwise. You can see two functions. Tried to attack function will set the variable to true and stop trying to attack to false. Of course, we need to add those functions to the attack action for performed phase, it tried to attack, which is the case when we press the attack button. For the case of the phase, it stop tried to attack, that will reset the bowl variable. Don't forget to remove functions when we disabled the player or controls, is the same procedure as before. Let's see the animation. I set the sample rate to 10. Let's go to the animator to see transitions. We can transition to attack from any state. Notice that we have one bowl parameter attack that needs to be true later individual aid, more conditions so that we don't get weird behaviors. Make sure that Ken transition to self is disabled. To exit the attack animation, we don't use condition. We use exit time of IT value one, which means that transition happens whenever our player attack has finished playing. Now, let's take a look at the script. I created this player attack control script. We can see references to the move controls gather input in the animator. We also have one bowl variable attack started to store information. If we successfully started painting attack. In the update method, we call the attack function. First, we check if the player press the attack button. So we check the tried to attack variable from the gather input. Then we need to check some conditions. I will do that in a moment. Then we start the attack. We use the animator component to set the parameter to chew. Now, if we press the attack button, the animation will play, but it will loop because we need to reset the animation parameter. For debt. We use the reset attack function, make sure it's public. Let's set the parameter to false. Idea is to call this function in the animation event. Go to the attack animation. And after the last frame, use the animation event. Choose attack function. Now, when you press the attack, the animation will play only one time. However, if you hold the attack button, you can use the attack all the time. If you don't want to date the behavior in the reset function, you can reset that tried to attack variable from the gather input script. Now you can hold the attack button and the player will attack only once. Let's add more conditions to animation transitions to solve some problems. For example, if you jump and press the attack, nothing happens until the player touches the ground, then the attack happens. To solve this, you need to select the transition to jump animation, then add a condition. A tech parameter needs to be false to play jump animation. Remember, when you add a new ability to your player, you need to update the transitions. Let's try it. Great. You can also add more conditions to the attack transition. For example, I don't want to play the attack animation when the player is that. So that parameter needs to be false. Also set the damage parameter to false. That means we can't attack when the player takes damage and hurt animation is playing. Now when we have good conditions, Let's set other conditions in the script. When we attack. Let's set a tech started to true. Of course, set it to false when resetting the attack. Before we start the attack, let's add conditions. If we already started the attack. Or we don't have control, then don't attack. We can also add knock back to the condition in the more controls change. Now back to public. Then we can use it in the condition. If the notebook is true, then return and do nothing. That's all four conditions. Let's add an attack collider that will detect enemies and do the damage. Selling the player and change sprite to a taking sprite. So debt we constrain the collider more precisely. Now we need one child, RGB. Call it player attack a, the polygon collider 2D. Use it as a trigger and then we can edit the shape. You can disable it. The idea is to enable it when the attack happens. In the attack controls create public polygon collider 2D variable. Let's create a public void, activate attack. This function will enable the polygon collider. Don't forget to disable it. In the attack animation, you can go to the first frame and add activate a tick with the animation event. So now we activate the collider, and at the end, we disable the collider and reset parameters. Don't forget to select the player and a collider from the child object. Let's create a special layer for the player at Tech. In the collision matrix. For now, I will enable the collision just with the enemy layer. Player attack object needs to be on the player attack a layer. Let's create a player attack script and edit to the child object. In this script, we detect collision with enemies and choose a tech damage. So we need one float attack the image variable and integer for the layer index. We get the index number for the enemy layer. Then we use the own Trigger Enter to d function. We check if the layer or the object that enters the trigger is equal to the enemy layer index, then we can damage the NMI. For now, just use the bug. Now when the player at tags the enemy, you can see debug message in the console. To actually damage the enemy, we need to go to the enemy script. Every enemy has helped and that means every enemy needs to have a function that will decrease health. This is why we create the take the image function in the parent class. Every enemy type can use it. This is familiar to you. This function will decrease held by damage amount. We can play some animation. Then we can do something when the enemy dies. For now, let's just destroy the enemy. Just to remind you, enemy is apparent class for patrolling enemy. In the prior attack script. Instead of debug, we can get the component NME and use the take the image function. In the inspector set, attack damage 250. The Patreon enemy has 100 health, which means it should be destroyed in two hits. One to grade. Let's say you have an enemy that doesn't move. If you tried to attack, nothing will happen. You need to change the rigid body settings of the player. Change the sleeping mode to never sleep. Now, we don't have problems with detecting collisions. Nice. You can see the enemy animation I made. This will be the challenge for the next lesson. But before that, let's do one more important thing. If you take a look at the attack animation is possible that the player takes the image in the middle of the attack, then the animation will be interrupted. The player place hurt animation. In this animation event that resets attack. We'll never get cold. That can be a problem in elite to double attacks. In this example, I will attack only once, but you will see two attacks. This is because the first attack was interrupted and we didn't reset the ethic parameter. We reset it after the second full attack. To solve this, we can go to the player stats script. We need a reference to the attack control script. Use again component in parent. When the player takes damage called the reset attack function. To remind you, this is the reset attack function and it will reset all variables and animation. Now, everything should be fine. There is no double I take, this is all for this lesson. See you in the next one. 59. Challenge + Review- Enemy Damage Animation: In this challenge, you need to create two animations for the enemy. One when the enemy takes the image N14 death also disabled the colliders so that enemy can't interact with the world after losing all health. First, I created the hurt animation. I used this wide sprite and change the color to red. Duration is 0.15 seconds. Then we have that animation. Go to the animator. You can see to trigger parameters. For the hurt animation, we use the hurt parameter as a condition. To exit the animation. We use exit time, a bit value, one. For death animation, we use the depth parameter in the enemy script. Instead of just triggering animations, I will create two virtual functions. In that way, every enemy types can have different behavior when taking the image. Go to the patrolling enemy script. Let's override virtual functions in the herd sequence, set a trigger hurt. In that sequence, we trigger the depth parameter. Here. We also need to stop enemy movement. So set speed to 0. If you remember, the enemy has a capes or 2D collider. And we have a polygon 2D collider on the child object. So disabled those two colliders. Use Get Component and get component in children. Because we disabled colliders, we need to set gravity to 0 so that the enemy doesn't fall to the ground. Let's try it. Great. Everything works as it should. See you in the next lesson. 60. Play Attacking Sound with Animation Events: To aid the sound for the attack, we need to select the player at Tech chart object, it, our audio source component. We can use the sword osha sound as an audio clip. I will change the volume and disable Play on awake. Now, we can go to the player controller script. A public variable, Audio Source. Idea is to play the attacking sound in the activate attack function. As you know from the previous lesson, we call this function in animation event. Inside the function, right, source that play. If you want, you can also stop the sound when resetting attacks. Don't forget to use the source from the child object. Let's try it. Make sure that mute out there is disabled. You can hear it. But I would say we need to increase the volume. I will try to its 0.6. Great, very simple and easy implementations. See you in the next lesson. 61. Challenge + Review- Destructible Box: In this challenge, you need to create a structural boxes to make sure that the boss can collide with the player and enemies. There are many ways how to do this. I will show you my solution, which I think is good when you need to scale your projects. This box has a rigid body 2D with a kinematic body type. It also has both collider 2D animator. Let's see animations. We have either animation, it's just the same sprite for two frames. Then we have box Hit animation. It's a white sprite. The sample rate is 60 and duration is 0.15 seconds later we set this to 0.1. Then we have books destroy animation. After the last frame, we have an emission event that has a cleanup function. That function destroys the box. You will see it. The box also has the box script. As you can see, the box class is a child class of distractible. Let's take a look at parent class. It has the hits to destroy variable, which determines how many hits the distractible object needs to take in order to be destroyed. Of course, we have the animator reference. You can see the heat distractible function that we call when the player attacks are distractible object, we decrease hits to destroy it by one. Then we call virtual function heat. This is a similar pattern that we used when damaging enemies. If hits are below or equal to 0, then use virtual function destroy. This approach with virtual functions is great because you can customize the behavior of each distractible type. Boxes can have one behavior, some other distractible object can have another behavior. Also, you can see the cleanup function that we mentioned before. It destroys the object. In the box script. We overwrite the virtual function to activate heat and destroy animations. If we take a look at the animator, we can see three animations in to trigger parameters, hit and destroy. To transition from idol to box hit, we use a trigger heat as a condition. To Exit animation. We don't use condition. We use exit time with value one. Of course, here we use destroyed trigger. I also created a special layer for destructive or objects. Let's go to collision matrix. As you can see, the structural layer collides with many layers. This is unique for every game. I chose Player and NMI layers. So that box can block the movement. Of course, I chose player attack, so we can destroy boxes. If you planning to use dynamic rigid body, the structural objects, then you need collision with the ground layer. To be able to stand on boxes, you need to add at the structural layer to ground detection in player MOOC controls. Now you can stand and jump from boxes for patrolling enemy. And at the structural layer 2 released so that enemy can detect the box and turn around. You can see an example. Finally, let's see how we destroy a distractible object. In the player attack script. We save the layer to an integer value. Then you need to create an if statement to check for that layer. Then you can get component disreputable and use the heat distractible function. To remind you, I will select it and press F4. And that will take me to the function. This is the function that we are calling in the attack script. And let's try it. Nice. But I think that white animation is too long. Let's decrease it to 0.1. Much better. I will repeat one thing in this lesson. If you have this problem when you are at taking and K2 destroy the boxes. But you did everything as I did in this lesson. Then you need to make sure that sleeping mode for the player is set to never sleep. I hope that you've all managed to solve this challenge in any possible way. See you in the next lesson. 62. Climb Ladders: In this lesson, I will show you how to make a leathers for the player. First, we need to decide what behavior we want. I like when the player must press the up or down button to attach to the letters. That means there is no automatic attaching when jumping through the letters. To detach from the letters, we use the jump button. And let's see the process. I created one tile map letters. The sorting layer is middle ground, and for the collision layer, I created the lighter layer. In the collision matrix, the letter Slayer collides only with the player. Let's create a tile from the Ally. There's a sprite. First, let's go to the Sprite Editor. Go to custom physics shape. Click on Generate. Now let's change the physics shape. It needs to be just in the middle. This will be our collider for litres. Select the tile palette and create a tile. Use the paintbrush to create some layers. Select the tile map. If a rigid body 2D, and choose aesthetic body type, it tile map collider 2D. Now you can see colliders intermediate offer letters. That's why we change a physics shape. Now, we can add a composite collider. Collide there needs to be used by composite. I like to use polygons as a geometry type, also enable the Is Trigger option. Now let's take a look at controls. I created one action, climb, its value with any type. To climb, I heard three bindings. They are one day composite, x is type. We use those bindings for vertical input up and down. If you need, you can also add X is dead zone for the stick. Now, go to the gather input script. We need one float value for vertical input and one public bowl tried to climb. You can see two functions. In the climb start, we get x is value from the buttons or stick. Because we use controllers, I decided to round the value. Don't know why. Please check the lessons about controllers. Next, we check if the value is greater than 0. I want to use both buttons up and down to attach to the ladders because the button for climbing down has a negative value, we use absolute value and then it becomes positive. In that way, we can press up or down to try to attach on letters by setting a tried to climb to chew. Note that here we're just trying to climb. Certain conditions in other scripts need to be met to actually climb. Then we have this climb stop function to reset the values. Don't forget to assign n remove functions. For performance phase, you as a client start for cancelled, climb, stop. Now we can go to the moon control script. We need three variables. One bowl on a ladder us to store information. If we are attached to either. Then we climb speed and the client the horizontal speed, the function. We check if we are online, then we can move left and right. You as a client, the horizontal speed in value x. But we can also move up and down user climb speed and value y. Somehow we needed to set the online there S variable to true. Idea is to set it to true when we enter the towel map trigger that we made before. Create a live script editor to the lighter star map. We need two references, one for gather input, the other four more controls. When we entered the trigger, get components. We don't need to check collisions if that is the player, because the layer ladders collide only read the player. Then we can use on triggers stay 2D. As long as the player is inside the trigger. And if he's pressing climb buttons, then we can say that the player is all letters. When the player exits the trigger, then we need to reset variables. First, let's see if we can climb in the inspector, set climbing speed and make sure that all leaders is false. Go to the riders and the press the Climb Up button, then climb down. Great. But if we don't press anything while we are on the gliders, the player will go down because of gravity. We need to correct this. We also need a way to detach from the others. In MOOC controls create one float variable, starts gravity. Then we can store our default gravity value at the start. When we are on the letters, set gravity to 0. Let's create a function to detach the player. First, we reset gravity by setting it to the start gravity value. Then we can set on a lighter stuff false. To detach the player, we need to jump from Delilah, go to the jump function. We can a condition that we can jump if we are on the ground or we are on the letters, then use exit aligners to detach. You can also use it in the double jump condition. In the lighter script, because the player can also exit the letters by moving left or right. We use exit aligners when exiting trigger. Now, we can go up. Gravity is 0. We can go left and right a bit. If we jump, we detach. Great. Let's create animations. I created the client animation. Here is the preview. In the animator, we need to create one bowl parameter. We can go to climb animation from any state. Change settings and disable can transition to sell. Condition climbed needs to be true. To Exit animation, climb needs to be false. Of course, you know that we must pay the more conditions as we add a new ability to avoid conflicts. That's in the image parameters need to be false to start climb animation. In MOOC controls, find a set animator values. And for the client the parameter use the own letters value. Remember, we call this function in the update. If you try it now, you will still have jump animation because of conflict. Select transition to jump animation and set climbed parameter to force tried. Now, finally, we have climbed animation. Next, we need to find our way how to stop the animation when standing still. But before, let's try to attack. You can see another conflict. To disable attacks on lidars, go to attack, controls, add another condition. We can't attack if all letters is true. Now try to attack and nothing happens. Nice. Safety. You can add a condition to transition the attack and needs to be false. The last thing we need is to stop climbing animation like this. Go to More Controls. When we are online, there's check for y velocity. If velocity or y is equal to 0, then disable animator. That will stop animation. Else enable the estimator to continue the animation. Also enable any meter in exit or lighters function. Well, let's try it. Nice. This is one way of making a Lidar system. Other systems can have an automatic attachment, may be there is no moving left and right or lighters and other stuff. See you in the next lesson. 63. Particle System- Gem Particles: In this lesson, we'll create a particle system and instantiate it when the player collects gems. To create a particle system, right-click in the hierarchy affects particle system. I will call it Jim particle. You can see a lot of options to change, but before we start anything, go to rendering. Then open materials use sprites, a default material. Now we have a nice square particles and we can see what we are doing. The first setting is the duration of the particle system. Duration is one cycle. Van de loop option is enabled. Usually people mix duration and start a lifetime. Start a lifetime is the life duration of particles, which means how long the particle will leave before it's destroyed. If I decrease the value, you can see that particles are destroyed sooner. So lifetime is for part coasts and this duration is for the system in a loop cycle. Some settings have more options. You can choose a lifetime to be constant curve, or maybe a random value between two constants. Let's choose debt. Now, some particles live a 1 second, some two seconds, and we also have values between. You can change particle speed. Let's change the start size. Of course there is the option to change color if you need. Then we need to set the gravity to one, so dead particles fall. Go to a mission. Here we can set the number of particles per second. For example, 20 particles per second. You can see more emitted particles. I will set this to 0 because we need to use burst emission. Now you can see all particles created at once. I will decrease the duration of the particle system so we don't need to wait five seconds for every burst. So one particle system cycle is two seconds. Next, you can choose a shape, for example, sphere, and then we have a different emission behavior. Of course, you can customize almost everything in options. I will decrease the radius. For this system, we actually need a hemisphere. Now, let's replace a white squares with a gem is sprite. We need to enable Texture Sheet Animation. Set mode to sprites. Then add the gem sprite. If you need, you can animate particles by adding more Sprites. You can also choose animation mode and so on. I will not animate this time. We have too many particles and let's set the burst count to 10. I want the different sizes for particles. So instead of constant start size, I will choose a random between two constants. You can see different sizes. Let's create our collision for particles. Change the type to world and set to 2D mode. You can see collisions. Let's decrease bounce. Much better. Increase the damping to decrease speed when a collision happens. And we can also decrease the life of particles on collision. Particles need to collide only with the ground layer. Next, we need to change the collider size for particles. You can see that the green circles are much bigger dense price. So change the radius is scale. Nice? I want to decrease the size of particles as time goes by, enable size over lifetime. This time, I will use a curve. You can choose some presets. Of course, you can customize it. The last thing we need to set the sorting layer. These particles need to be ahead of everything. So choose foreground. When you are done with testing, don't forget to disable looping if you don't need it. Click Play to see the end result. Because the loop is disabled, it will play just once. And let's make a prefab, drag it into the prefab folder, select the gym prefab and go to the gym script. We need one end game object variable. When the player collects a gem, instantiate the gym particle object a to the same position. It Jim particle prefab to the gem is script. Now, everything should work. We can delete the gym particle from the scene. I will add more gems. Let's try it. Great. The particle system is a really powerful tool. We just scratched the surface. So feel free to experiment with other settings. See you in the next lesson. 64. Main Menu Preparations: The goal of this section is to create a simple main menu from which we can start the game, go to credits and exit the game. We learn how to use text Mesh pero, and how to correctly use n connect buttons with scripts. You know that we created the main menu scene that is just a copy of level 1. Now we can open it. I deleted most of the objects that we don't need and edit the fader prefab. You also need to have main camera, virtual camera, empty canvas, and events system. We use event system to navigate it through buttons in other UI elements. Note that for now we use the default controls for UI. If you are making the main menu scene from scratch, then make sure you replace the input module on the event system. We can open default controls that are provided by unity. Under UI action map, you can see actions that we can use to navigate through UI. Later in this section, we create custom UI controls. Remember that in our controls we have the UI action map that we didn't use yet. The last step I will do in this video is to change the background color. Select the main camera. I want to use color from background, tile maps. Great. Now we can start creating the main menu in the next lesson. 65. TextMesh Pro + [MiniChallenge]: In this video, we learned how to use text Mesh probe. First of all, why we use text Mesh probe, the most important thing is that text Mesh Pro has more options to customize the text and it allows better text is sharp and crisp, which is not the case when using default text from Unity. Texts from Unity has so much blower and sometimes it can look very bad. That being said, let's use text Mesh Pro. Under the UI section, find texts, texts. If it's your first time using text Mesh pro in the project, you need to import DNP essentials. Let's call this object game title. In the inspector, you have the text field where you can write your text. Note that you can change the size of the text area by using erect tool. Then you have some standard options. Font, font, style, size, color, even color gradient. Pretty much standard options that you have in Microsoft Word. And let's change alignment to the middle. You can explore a wrapping and our flow later. Now, let's try to change the font. Here we have the custom font that we imported the before. Tried to add the font and nothing will happen. You can't do it. That is because we need to make font S at first. Go to Window, takes mesh Pro, and open a font creator. Drag the font here. Then it's important to choose a render mode. It's different for every font type, usually smooth and SDF are good. But for the pixelated font that we use, we need a raster mode. Click Generate Font, atlas. And we have one missing character and others are fine. Save it. Now we can use to change the font. Grade. Remember, we need to create a title like this. So let's create one image. Change position and anchor to the middle left. Move it up. Now we need to change a sprite. I will actually use a sprite and change the size, change the color. Let's see it in the game. We know we need to disable, pay their Canvas to see it. It looks nice. Now the texts should be a child of that image. Hold the Shift and Alt to center it. Change the size a bit and write the title. Great, maybe move it up a bit. Now, just a small digression. I will show you how to use text Mesh Pro in scripts. It's not straightforward. I will create one new object and the example script. To use text Mesh Pro. First, we must include namespace am pro. Then we need to create the variable takes mesh pro, EU GUI that I call element. From that element, we can get the text component and set the text value. Now, use game titled texts as element. Press Play. You will see the result. Your mini challenge is to replace text that we use for Jim numbers. You should use texts mesh Pro. And that's it. See you in the next lesson. 66. Buttons and Main Menu + [MiniChallenge]: In this lesson, we'll learn how to make functional buttons and more about UI components. To create buttons, we can also use text Mesh Pro package. Go to you, I select a button with TMP. This will be the Play button. You can see the button component in the inspector. Note that we also created one child object. It's the text for the button. Let's change it. Use a custom font. Now, let's add functionality to the button. Every button has onclick event, and let's add one. This will determine what will happen when we click on the button. In this case, we need to start the game, which means change the level. If you remember, on fader Canvas, we have fader script and let's open it. This script has a public function, set a level that will change a level. We can use it with the button. First, make sure that the object is enabled. Then select the button and drag the fader object to the empty field. Now, we have access to all components from the fader object. We need a DFA, their script. Then find the set level of function. I repeat, function must be public. Since the function takes one argument, and that is the level number we can choose. Which level too loud. Let's try it with the built index 0, which will allow the main menu. Again. Press the button and it will load the main menu level. Let's change built index to one. Now we go to the first label. Great, because our testing IOS set the value to 0. Now we can change visuals for the button. For the source image, I will use Health Bar sprite. By default, transition is set to color tint. That means that the button changes color depending on the state. The normal color will be brown. Let's change the text color. Highlight that color is color when the mouse pointer position is over the bottom. I believe a oppressed, a color as gray. That is, when we press the button. This is the color for selected button. Let's try. You can see highlighted color. If I press and hold the mouse button, you can see pressed color. The text is not in the middle. Let's quickly fix that. To add more buttons and organize them. And let's add one empty object. I will call it a button parent, change position, and anchor to the middle left. Actually, it needs to be a child object of the title image. Then anchor position is the mineral bottom. Set position in depth way, it's always below the title. We can change the size. The Play button will be a child object. Now, we can duplicate the button, change the text for each button. The next step is to organize buttons, select the bottom parent and a vertical layout group, vertical layer with group has control over child objects, in this case buttons. So let's set alignment to the middle of center. Watch the buttons. Nice. You can also change space in padding between buttons. If we change the size of the parent object buttons, we'll adapt. If you add more buttons, the same thing. Note, when we start playing, buttons are not selected by default. To change that select event system in for the first selected object, set the play button. Now you can see selected color on the play button and we can navigate with UI controls. You can also control how the buttons are connected. You can see the lines between buttons that give you a connection information. You can turn them off an own V8 visualize button. Also, you can change the connection. Sometimes automatic connection will connect the buttons that don't need to be connected. Then you can use explicit connection. You manually set what button will be selected if you press the up, down, left, or right navigation button. From the play button. If we press up, we go to the Create button. And if we press down, go to the credits button. Nice. Later, we will set the explicit connection to all buttons, but we for, Let's add functionality to the Quit button, open fader script, and create the public exit game function. To use that function for the Create button. Now, let's add functionality to the credits button. We need to create something alive. This image with text and one button. Create one image, stretch it, and change color text. We can duplicate one button. Change. Then we need to disable credits panel. Idea is to enable it when the credits button is pressed. On click event drag gradients panel. Use GameObject and the function set. The bowl variable needs to be true. Let's try press credits. The panel is enabled. However, you can see that the back button is not selected. And with UI controls, I can switch back from the main menu buttons and this back button. Let's fix that. It. Another onclick event on the credits button. Drag event system. Use function, set selected game object. When we press the credits button, select the back button. You can see that the big button has connections to other main menu buttons. This is the problem. Set the connection to none. And when we press the back button, we need to disable credits panel. Also set the credits bottom to the selected button. Let's try it. Press credits. The big button is selected. Price it, and the credits button is selected. If you want, you can set the explicit connection to all buttons. Great. This concept is functional, but I will show you one trick on how to improve performance. Sometimes enabling and disabling UI elements can be performance expensive. To avoid it, we can add canvas group to credit Spanner, set alpha to 0, and set the bowl variables to false. Now select credits, baton, and instead of enabling object, use Canvas guru. Set alpha to one. And also set bowl variables to show the button needs to be interactable in turn on a rapist, so we can use the mouse on buttons. Now, your mini challenge is to use Canvas group. When the big button is pressed, you need to set alpha to 0 and set the bowl variables to force. That's it for this lesson. See you in the next one. 67. Challenge- Custom UI Controls: In this challenge, you needed to create custom UI controls. I will show you how in one example and then you need to continue the challenge. So if you select event system, you can see the default controls that we use. That controls are from default input actions. You can see, for example, navigate action in bindings. To move through UI elements we assigned navigate action. You need to see it. Remember the correct value type. Devin, go to your controls. In UI action map, create the same or similar controls. For navigation. The type needs to be vector to add bindings. Save it. Then you need to replace the controls as set. For more US. I navigate customs that we made. You needed to create and assign actions to other behaviors. Quick tip, you can copy the action and paste it into your controls. My recommendation is that you don't copy and paste doing it step by step manually, you will learn more than just copy paste. When you are done, you can add images and animation surrounded main menu looks better. I created one empty parent object that is stretched it to full screen. All decoration images are child objects and I control them with the Canvas group. When the player presses credits, alpha becomes 0. And when the back button is pressed, it becomes one. That's it. See you in the next lesson. 68. Pause Game + [Challenge]: Let's see how we can pause the game. First, we need to create pose action in our controls. In the UI action map, create action and choose binding. I will use P. Save a set, then go to the gather input script. We need one private bool variable pose. It's important to set the value to false. Now, we can enable pose action. Of course, we need to disable it on, Disable. And let's create a function in which we actually pause the game. Same procedure as before. In the function, first, we need to set the variable to the opposite value using the exclamation mark. For example, if the value is false, then it will become true and vice versa. Then we need an if statement. If pause is true, then set timescale to 0, that will freeze time into gate. If the post variable is false, then a set of timescale to a normal value of one. Fun fact, you can speed up or slow down your game using timescale. Next thing we need to assign this function to the performed a phase. Also, remove it on disable. Let's try it. When I press P, the game will stop. Press B again and it will continue. However, the sound will not stop. I can pose the game, but the sound is still playing. We have a simple solution. Use audio listener dot pose and set it to true. Of course, set it to false when we continue the game. And let's try it. We press the button, everything stops. But be careful, update functions will still be called. For example, I will use this update function just to debug. Let's pause the game and you can see that the update function is running. So it's good idea to disable and enable player controls. Your challenge is to create a simple pose menu, buttons and other UI elements. So when the player presses the button, the menu should appear. At this point, you know how to enable and disable UI elements, have to create buttons and other UI stuff. If you have any problems, you can contact me on the Discord server or any other social platform. See you in the next lesson. 69. Load Saved Level (Continue Game): Let's see how to save a life so that the player can continue to gain. Usually, you can create a separate button to continue to gain. But for simplicity, let's use the play button to start a new game and also to continue to remember, the Play button uses the fader script to load the first level. Let's go to the failure of script. This is the function we use. Now, let's create another public function. To set a level to load. You use a player prefs, get int. The key will be saved level for the default value used the index of your first level. Then start fade animation. Select the play button, and now you use the function that we created. The next step is to go to the level one, create a new object and new script, save a level. Open it. If we need a senior management namespace in the start function, idea is to save the index of this level. So use the player prefs set int, make sure you use the same key from the fader script. Now, say the index of this level. You can make a prefab from the subject. The next step is to place that prefab in every level, go to level two in the prefab. So now when the player enters the level, the prefab will save the build index. Let's try to start a new game. Go to a level to exit the game. Start again and we start from a level two. Great. See you in the next lesson. 70. Export/Build Game: To export or built, again, go to File, Build Settings. You already know something about this section. You need to include your scenes, slash levels. Then choose the target platform, depending on the modules you have installed, you can choose which platform you want. I have the mic module, but this will be again a for Windows, you can choose architecture 32 or 64 bit. Let's go with 64. Then you usually go to build. But first, let's change things like the game icon in the splash screen. Go to Player Settings. This will open the project settings with players section. First, you can change some info about your company and the game. Then you can set the default icon. I will quickly import sprites. You can download them from the resource folder. And let's use this sprite as the icon. Here. You can change your cursor. I don't have a custom cursor now, but if you add one, make sure you change Texture Type 2 cursor. Next, you can override your icon. We set default icon, and this is just an option to replace it for PC, Mac, and Linux. Then you choose in which mode you want to run your game. For me, It's full-screen window. You can also choose a supported aspect ratios. At this time, most of the pointers have a 16 to nine or 16 to ten ratio. Then we have the splash image section. Let me just move this from the middle. Click on the preview button and you will see what will be on the screen when you run the game. This is free Unity version, so you can remove the unit tail over, but you can customize the some options in your logo. Let's add the route Games logo. Nice. You can choose to show logos sequential, one after another. And you can choose the duration. You can explore more options, change the background color, and if you want, you can add a custom background image. I will skip that part. Let me just change it back. Hello goes to one below another. Now let's go back to Build Settings. Click on the Build button and choose one folder. Unit 3, we'll build the game. You can see that we have a custom icon. Let's open the game. Here is the splash screen. And now we can play the game. Congratulations on completing this platformer section. Next, lessons are not project-based. They are separate license covering the specific topics. You can vote for the next license on the Discord channel. Thank you again and see you later. 71. URP Setup: Universal render pipeline, or ERP is unity prebuilt to render pipeline depth provides you an easy and quick graphic optimization. For example, to the lighting, shadows and glow effect and other post-processing features. It's a super optimized, so it can be used not only for PC or a high-end Kozol's bath for mobile and other low-end hardware as well. Now that you are used to be called a lightweight the render pipeline. You and create ULP project in the Unity Hub that will automatically set up ERP. But if you already started with the basic 2D template project, it's easy to upgrade it. Let's choose that approach. So this is a basic QD project to import ERP, go to the Package Manager, us packages from the Unity Registry, search universal render pipeline. Install it. It will take some time. Then go to create rendering. You RP and choose a pipeline S at. Unity will create two things. One is the EU RPA acid and the other is the renderer. By default, it's a forward, a renderer. If you click on the asset, you can see that S, it uses a forward render. However, we needed to create another renderer for 2D games. Again, go to create. This time, choose a 2D render. Select the exit and a drink today renderer. Now we can delete the forward renderer. Next, go to Project Settings. Under graphics, we needed to assign that you RPA set. Now we need to upgrade the project. Go to Edit Render Pipeline, TURP to the renderer. Here, you can choose to upgrade the scene or the whole project. For this example, I will choose the algorithm, just this scene. You can see that everything turned black. That is because Unity change materials for sprites and we don't have a lights. For example, select the player. Under the material field, you can see sprite elite material. This material is sensitive to light. If you choose unlit material which is not sensitive to light, you can see the player. Of course, we need a lithium material. If you don't see those materials which tried to total the Hide button. And that's it. You IRP is correctly set and ready to use. For example, now we can use it to create a 2D lighting. This is material for the next lesson. See you soon. 72. 2D Lighting: To create, to the rights to right-click and go to to D. And you'll see the list of available light. Let's start with the global light. You can see that sprites react to the light. For Global Light deposition is not important. It's a global and it will illuminate all objects under selected the layers. You can choose a sorting layers to eliminate this, global light needs to illuminate all layers. Of course, you can change intensity and color. Ios set intensity to allow value for dark ambient. Note that you can have more global lights, but they can't eliminate the same layers. You can see errors. This global light will be just for the player. And for other global light, you can exclude that layer. Now you can increase intensity for the player so that he stands out a little bit. Great. Let's create another light. Choose point, a light. Set all layers. For this slide, you can see more options. You can change the radius. There is also the inner radius. Falloff intensity is for smoothing the light. If you set it to 0, you get a sharp light border. The cool thing is that you can create spotlight from a point light change inner and outer angle. Then a rotated delight. For adjusting the light. You can also use a yellow gizmos. Let's change color. This looks nice, but of course, it can work much better. You just need time to find the right options. Feel free to experiment. And let's duplicate the light. Next, let's take a look at free form. Alight. Select all our layers. As the name says, we can form any shape that we need. It's easy to add more nodes for adjusting the light. For example, you can use a free form light to illuminate the exit from the level. Let's quickly change the shape. Here we have the option to change the fall of offset. It's a bit too bright, so decrease intensity. Let's try it. Nice. Next, let's create parametric light. Parametric light allows us to make lights with x amount of sides. We have a slider to change the number of sides. The smallest number is three, which creates a triangle. Then you can increase sides to get other geometry shapes. I will not use it now. The latest light type is a sprite tried. For this slide, we use sprites as illumination shapes. You can see this bright field. And let's use one of the sprites that I prepared for. You can download it from the resource folder, drag the sprite into the field. Now you can see that the light shape is based on the sprite. Let's move it and decrease intensity. This looks nice and we covered all light types. I will show you one more option. Notice how area light has a blend style option. We have four blend modes, multiply, additive, subtractive, and custom. Blend modes control how light affects sprites matter if you change to a different style number, nothing happens. You need to select the 2D render. You can see for blending slots, blends 0 has multiply mode, which is a default mode. Blend one also has multiplied mode. We can change it to another. For example, edited. Then select the light and change the blend. This style. You can see that the light behaves differently. Here is the picture from unit is official site. You can see how each mode affects Sprite. I will switch it back to blend 0. I just wanted to show you more options that you can use. This is all for this lesson. See you in the next one. 73. 2D Shadows: Hello everyone. In this video, I will show you how to make 2D shapes. Before we start, I will assume that you know how to set up your ERP. And today lights in the scene, I have the platform and light to create shadows. Select the platform. We need to add the shadow casted or 2D component. The next step is to select the right and increase shadow intensity. Now you can see the shadow, but the shape is not precise. So select the platform again and use Edit shape to customize your shadow. Note that you can choose on which layers you want to cast shadows. That's it for this video. See you in the next one. 74. Post Processing: With post-processing effects, we can easily improve visuals and make the game more attractive. For example, we can add glow to the bright areas. We can play with colors, it all sorts of filters to the screen and so on. Before we start, Quick Info to avoid confusion, post-processing is integrated into the ERP. If you find the post-processing package, is the package manager, don't install it. This is the old implementation and it's not compatible with ERP. We have all effects and everything we need inside ERP. So let's start. First thing. We need to select the main camera and enabled post-processing. Then we can implement post-processing in two ways, depending are you using Cinema machine and virtual cameras or you don't. It's a very similar implementation. So let's start with an option. When you don't use cinema, she right-click in the hierarchy, go to volume, choose Global. Other volumes are usually for 3D games. The next step is to create a volume profile. You can do it by clicking the button, or you can go to Create Volume profile. It, the profile. Either charity effects are called overrides. So click on add, override, choose post-processing, and you will see the list of available effects before we go through them. And let's see implementation. When we use a cinema machine, you can delete the volume, but elif the profile, select the virtual camera became one in this case. Go to Add extension and choose Volume Settings. Then edit the profile that we created. Again, we have the add override button. Now I will show you some effects. The most common effect is blown. The balloon will add the glow to the bright areas. First, you need to enable what settings you want to use, a brown the effect. Let's enable threshold and intensity. If I increase intensity, you can see that everything starts to glow a bit. To limit glow areas, we use threshold. The threshold determines how much an area should be bright to apply the effect, set threshold to a high value if you need glow only for bright areas. For example, let's select this bright light, increase the intensity and you will see the glow effect. Lowering the threshold will include the darker areas and give you more glow. You can see how it looks in the playground. It can look a bit weird if the light is in front of the player. If you wanted the player to be in front, then exclude the layer. Now it's much better. We can also use glow to improve the look of the lamps. You can increase the intensity or point lights and that will create at low. But to be more precise, Let's create a free form, a light. It needs to cover just the yellow part of the Lamb. Set fall off to 0, increase intensity. Our course set of layers. You can see a small glow. We can improve this even more. Let's exclude the player. Go to bloom options. Enable scatter. The scatter controls the spread of the globe. I usually set this below 0.5. Then we can change the color of the glow. Let's go with orange. You can also see it on the sprite slide. This looks nice. Of course, you need to change the color of the spotlight. It's two grid, but that's up to you. Let's move on it. Another override. We can try color curves. With color curves, we change the luminance of the image. The bottom of the graph affects dark parts of the screen and the top of the graph represents the brightest areas. To change the curve, click on the override. If I pull down the top value, brighter areas will become darker. If I pull up the bottom part, dark areas will become brighter. You can remap luminosity as you wish. Also, you can do that for each channel, red, green, and blue. You can also see some other curves. I will show you one. Let's see Hue vs Saturation. If you pull down the curve, you get a grayscale image. In this curve, you can adjust the saturation, a specific hue. For example, let's turn up just orange and yellow color. Feel free to check other curves. Let's see, white balance. White balance allows us to adjust the color temperature from warm, yellow to call the blue, is the same with teeth, but it's between purple and green. There is also the vignette effect. Go to the game window to see changes. Let's see another effect with film grain. You get the old localized on ancient TVs. And this is all for this lesson. I showed you how to implement post-processing and some cool effects. Please explore a try other effects. See you soon. 75. Screen Shake with Cinemachine: Hello everyone. In this tutorial, we'll learn how to quickly create screen shake using Cinema sheet. I will assume that you know something about Siena machine and you have to add virtual cameras. I will create a screen shake when the player collects the gym in when he destroys the box. First, select your virtual camera, then add one extension. We need a cinema machine, impose a listener. This component will listen for screen shake impulses in the VA. This is a 2D game so used to the distance. Next, select the gym ed component. Search for cinema machine collision impulse source. This will trigger a screen shake when objects collide. Next, we need a signal for the impulse source. Create new noise settings. This will be gem screen shake. Select noise settings. Now we can adjust the screen shake for each X is, select the x-axis and click on the plus button to add the frequency and amplitude. Frequency is how fast the screen will shake, and amplitude is the strength or the shake. Let's add some numbers. You can add multiple frequencies and amplitudes. Then add numbers for y-axis. For 2D games, you don't want to use z axis. Also, if you need, you can change a rotation. Now select the gem. In the impulse source settings, you can adjust all amplitudes as the frequencies or the signal. Then you can adjust a fade in and fade out the times of screenshare using time envelope, the attack is a fade in into the shake. I will set this to 0.1 seconds and adjust the graph. Sustain time is the duration or the shake on maximum strength. Decay is a fade out time. The next important setting is to choose what the layer will trigger the shake when objects collide. For a layer mask choose, the player may sure that the player is on that layer. Let's try it. Great. This screen shake will work for 2D and 3D games. Now, let's use a bit of coding to create another shape when we destroyed the box. Let's select the box. This time, add impulse source without collision. Again, you can create another signal specific for the box. But in this example, I will use jam signal. I will not change any options. Go to the box script. We use inheritance and virtual functions. This function is called when the box is destroyed. Inside that function, we need to start Screenshare. First, import the cinema machine namespace, then create impulse, source variable. In the start function get component. Soviet can get access to properties and functions. In the destroy function, use impulse source to call generate impulse function. That's all we need to code. Let's try destroy the box so we can see the screen shake. Nice. Thank you for watching and see you soon.