Make a 2D Platformer Character with State Machines in Unity 2020 | Christopher Navarre | Skillshare

Playback Speed


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

Make a 2D Platformer Character with State Machines in Unity 2020

teacher avatar Christopher Navarre, Software Instructor

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

10 Lessons (2h 6m)
    • 1. Introduction - What to Expect

      1:40
    • 2. Project Setup, Assets, and Creating a Player Prefab

      12:00
    • 3. Setting Up Run and Idle Animation in the Animator Controller

      9:54
    • 4. Controlling Animator Transitions through Player Input Script and Animator Parameters

      15:24
    • 5. Building Ground on a Tilemap to Stand On

      6:40
    • 6. Movement Scripts & Dynamic Rigidbody

      27:15
    • 7. Air States Falling, Rising, Jumping, Landing, and Double Jumping

      28:29
    • 8. Wall Jumping State & Bug Fixing

      21:25
    • 9. Adding a Background and More Ground for Character

      2:21
    • 10. Cinemachine - Easy & Smooth Follow Camera for Your Player

      1:18
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

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

321

Students

--

Projects

About This Class

This course will show you how to take an animated sprite character and use it in Unity engine to setup a fully playable and animated player character GameObject. In this series, we will utilize the unity animator component & state machines to allow our character to transition from one animation like idle, run, jump, and wall jump to the next at the correct time. We will also cover how to setup character movement scripts for moving the player's rigidbody. By the end you should have a functioning 2d platformer character with a clean state machine setup and nicely separated state machine behaviours for controlling each state (or substate machine when you want to apply one script to multiple states at once!)

  • Create a 2d platformer character with movement scripts for running and jumping around your level.
  • Especially meant for beginners who want to build their first controllable characters inside of the Unity engine.
  • Sprite based animation setup. How to create animation clips
  • In the course we'll set up and make running, jumping, double jumping, wall sliding, and jumping off of a wall slide. 
  • Same basic principles can apply if you need to make attack states, dashes, slides, or the like in the future.
  • Using the Unity State Machine System.
  • Transitions, State Behaviour Scripts, and Substate Machines
  • How to talk to and from the animator when getting player input and assigning forces to your Rigidbody character
  • How to Create Tilemaps and setup collisions with the ground and walls
  • Let states hold code that are specific to that state to separate tasks.

254426a9

Asset Credits

Pixel Adventure Art Pack by Pixelfrog

Intro Music - Ludum Dare 38 Track 10 by Abstraction

Meet Your Teacher

Teacher Profile Image

Christopher Navarre

Software Instructor

Teacher

My philosophy in information technology and learning in general is that video learning is the best way to learn for yourself. I can provide the videos but it's up to you as my student to absorb and practice the information to become a more educated and skilled person.

If you want to get a taste of my approach to education and tutorial series, you can find me on my YouTube tutorial channel Chris' Tutorials.

See full profile

Class Ratings

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

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

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

Transcripts

1. Introduction - What to Expect: Hello everybody, Chris here. And in this series I want to show you guys how we can set up a 2D platformer character inside of Unity utilizing dynamic mode rigid bodies. So this course is especially men for beginners who want to build the first controllable characters and side of the Unity engine. We're going to be using a sprite based animation setup. So frame-by-frame animation. And I'll be showing how to take our assets and to create animation clips as they exist within Unity so that you can actually use them on your character. In this course, we'll be creating and setting up, running, jumping, double jumping wall sliding and jumping off of a wall. Slide animations. The same basic principles are going to apply if in the future you need to create a tax state stashes slides or the like. We'll be using the Unity state machine system, which is a visual way of transitioning between motion such as idle, run or jump by using nodes and then connecting those nodes with transitions for each of those nodes when He also need them to do specific behaviors, you can attach a state behavior script that will only run while the character is within that state. I'll be showing you in the course how to talk to the Animator component attached to your character by using animated parameters. So when you're getting player import or assigning forces to your rigid bodies. You can also share that information with the animator parameters, which can be used in your transitions or behavior script's, being that this is a 2D platform. Of course, I'll also show how to set up tiles and tile maps so that you can create ground and walls for your character to move around, jump on and while slide off. So if these sound like the kind of skills you're looking to learn right now, then I hope to see you all in the first video for the course. 2. Project Setup, Assets, and Creating a Player Prefab: So for this series on setting up a 2D platformer character inside of Unity, I'm going to be using this back called pixel adventure off of H dot IOL by pixel frog as a bunch of really cool characters, enemies, and player characters that you can use for a platformer game. And the different player character sprites inside of this pack have very similar animations. So I think that this will work out really good for this tutorial because the different characters in the pack or have the same animation. So if you want to switch over to a different character, you can pretty much follow the same steps. Alternatively, if you have your own 2D platformer character animated in a program like ass upright already. You can use that instead. So I'll include a link on getting to this page so that you can download the assets at the bottom, you just gotta click download now, and you can go ahead and grab the pack, download it, and save it to your computer. So the next thing that we're going to need to do is to start a fresh 2D Unity project. So I assume you already have unity hub and some version of Unity installed. Currently I'm running on 2020.1.9 f x1 f for final, I believe. And we can start a new project by going over to nu over here. So we want 2D, since this is a pixel art game. And we're going to go to Project Name. And then you can give the project name anything you want. So I'll call my project platformer character, and then let's go ahead and hit Create. So when we boot up our project for the first time, we should see a layout similar to this is not critical, but if you do want it to be exactly the same, you can go up to window layouts and then revert factory settings and you should get the same look. So inside of our project window, that's in the bottom left-hand corner here. We're going to want to bring in our assets that we downloaded so that we can use them. So what I'm gonna do is right-click to create a new folder. So I'm gonna go to Create folder, and I'm gonna call this r. So what did you decide to set up your folders in your project is completely up to you. But what I like to do is put my art assets into a folder called art. And then the assets I'm bringing from outside sources like H dot IO, pixel frog. I'll put it in the imports folder so I can remember that I got it from somewhere else. So I'm going to go to create folder here and I'll call this imports. So now if we double-click into this where an assets are imports, and then we need to bring the pixel characters enter here. So I'm going to drag this window slightly out of the way and double-click on the zip file for the, and then double-click on the zip file for pixel adventure, we can double-click into free to see all of this stuff that exists inside of this pack. But when we extract it to the project, we probably want all of these dystopia contained within one folder. So I'll navigate back up to where we have the free folder. And I'll extract this to the desktop rather than leaving it with the name pre, which doesn't really tell much, I'm going to rename it with F2, and I'll just call this pixel adventure and a dash and pixel frog for the author name. And now to bring this into the project, we can just left-click on this, hold it and drag it into imports. So you should see this little icon next to the cursor. And if you see that and you let go, it's going to add all the files into the project, okay, and now we can go back into Unity Foley, and we can check our imports folder for the acids inside of there. So this tutorial is focused around creating a main character and animating it. So we're going to double-click into main characters. And you can see that this four and this pack, there's Mask dude, ninja, frog, pink man, and virtual guy. So you can double-click on each of the folders and you can see the sprites that exist inside of each of them and get a sense of which character you might like. And I believe that they all have the same animations. So once again, you can pretty much choose whichever character you'd like for me. I think I'm gonna go with virtual guide for now. So the last thing we'll do in this video is to create a game object which contains the sprite for virtual guy. So inside of the default scene that's loaded up. And if you want to rename that, we can just go back to assets folder scenes, and then find the scene and rename it. So we'll just call it tutorial scene. I guess that would be a little bit clearer and reload. So now you can see the name changed up here. But inside of our scene, we just need to basically drag and a sprite of some kind. So let's create our character game object by bringing a sprite. And so let's start with idle. So the default animation and the probability the first one we're going to work on is going to be the idle state where the character is not doing anything. And really if you look at this, you can see that there's actually many different sprites inside of here. So this is really a sprite sheet. But for right this second, just drag it into the hierarchy of the same. So when you do that, you'll get a GameObject that also has a component called a sprite renderer. The sprite renderer allows a 2D sprite to be rendered visually onto the screen. Basically, your images, you can see them in the game object and you can animate this later on it and all that kinda thing. So one of the first things you're probably gonna wanna do is rename this character. So instead of calling it idle 32 by 32, I'm going to go up here for the name of the game object, and I'm gonna call it player, makes a lot more sense before I fix anything else. Another thing I wanna do is go back to the assets folder, and I will create a new folder here for characters. And so inside of this character's folder will store the prefab for our player game object by left-click, dragging it in here, and then it gets stored to this player dot prefab file. And the prefab basically is a copy of the game object that's stored inside of our assets folder, which we can instantiate onto a scene or basically create a copy of by dragging it in here. And then when we have these copies, we can change details about them. So for instance, we can increase the scale of the gameObject to make it bigger. And that changes this copy, but it doesn't change the original. And so this instantiated copy has different values now, like the scale. But if I double-click on the original prefab, you can see that the settings still have the scale at 11. If you want to change something across all objects, you would set it in the prefab. And if you want to change something about the copy of that prefab, you would just change the one that's inside of your scene. One of the reasons we need the prefab right now is that if I was to accidentally let say, delete the player from the scene and hit control S, Save the Project. That player isn't completely gone. We started the prefab as a file here, so we can add it back to the scene quite easily and we don't lose our work. So having a prefab for any game object that you're working on is a really good idea generally. So two final problems that we need to fix before we wrap this video up. One, the sprites look blurry, so the Pixar, so they shouldn't have any anti-aliasing. The edges there, there shouldn't be any blur, there should be crisp pixels, so we can easily fix that. And secondly, we brought our entire sprite sheet into here. It should actually only show one of the sprites at once. So to fix both of those, we need to go back to the folder where we have the virtual guy character or whichever one you decided to go with. So if we click on any of these imported sprite assets, you'll see a bunch of settings. For instance, sprite mode set to single. So if you have a sprite sheet where actually has multiple sprites for different frames of animation. You need it to not be in single, but rather multiple mode. Secondly, on all of these sprite assets, you'll see the filter mode is set to be linear per pixel at games, you should have that set to point to save time, we'll editing those. I'm actually going to left-click on the first spreadsheet inside of here, hold shift down and then left-click on the last spreadsheet. So what we're actually doing here is selecting all seven of these texture 2D objects. So now if we change a setting like filter mode from bilinear 2, which you should do now. Then we can apply it to all of them at the same time. So hit apply. You should see the character inside of the scene become much crisper. And if we bring in any of the other assets, you should see them render properly with none of the blurriness around the edges. So now it looks more like proper pixel art. Okay, now the other thing for Sprite mode, not all of these are actually sprite sheets. Some of these are single frame, so the single frame ones should be kept as single frame. So what you can do is left click on the sprite sheet that actually has multiple frames. Hold Control down, and then left-click on each of the other ones that are sprite sheets. And then we can change it from single mode to multiple mode and then hit Apply. So now when we do that, it looks like our player disappeared. If we double-click there, it's missing a sprite. So not a huge deal there. What we can do is actually break apart our idle sprite sheet and then set the correct frame to appear here. So I'm going to left-click on the idle sprite sheet. We're gonna go into the sprite editor here. So left-click bat in the Inspector. And then we need to slice this out by the number of rows and columns that are across the sprite sheet. So go down to the slice menu, choose slice type, and make it grid by cell count. So we can count the number of columns here. Obviously the rows are one. So 1234567891011. So we need to put 11 and for columns and one for rows, hit slice. And poof, you have a perfectly separated sprite sheet, assuming that the sprite sheet were setup correctly to begin with. So whenever you export a sprite sheet from a program like acid, right? Each of the frames should have the same width and height. So you can see here they were 32 by 32. So this sprite sheet was done properly. And that's one of the things you have to watch out for whenever you are exporting a sprite based character. So now that we have our frames properly separated, we can apply up here, and now we're going to have 11 separate frames. And we can see all of them by hitting this little, looked more like a play symbol here. And we have our 11 frames separated here. So now with player, you can see we still have the missing sprite, right? So what we need to do is just left-click on this first frame with this sprite sheet expanded and drag this into missing sprite. And now we have our player there. We can double-click on it to zoom into it. You can see that the pixels are very crisp. A character as the sprite renderer has a name and has a prefab. So one thing that we maybe should have done actually is edited this change on the prefab. So if I click over here, open prefab asset, you can see that the prefab is still missing the sprite. So if you want to change a setting that applies to all of the instances of the character, then you should do it in the prefab mode. That's the quick way to do it. And then you can just drag it in here. But let me show you another way. So back on the tutorial, seen our player, you can see that the sprite field here, this bright property, um, is a little bit highlighted here. So what that means is that there has been a change that's different from the prefab. And we can apply it directly to the Prefab here by right-clicking and choosing apply to prefab player. So now if we go back into the prefab by clicking on the arrow, you can see the Prefab now has the sprite idle frame 0 as well. And if we go to our characters folder and find our player prefab, you can see it's in the preview there. And we can also just keep dragging copies of it into the scene like a madman. And yeah, we have six players in the game, which is completely unnecessary. So I'm gonna delete all of them. Okay, so, so far we've actually made a lot of progress. We have the assets inside of our Unity project. We have a player prefab with a sprite renderer. It's properly rendering the idle frame. We've separated, we've corrected the import settings for our sprite sheets for a pixel art game minus1 thing, which is that except for the idle sheet, we haven't gone to these other spreadsheets and separated them properly using the sprite editor, which you should usually do whenever you need a sprite mode multiple. But we will do that in the following videos. So that's gonna be it for this video. I hope you guys are following along well so far and I will see you guys in the next one. 3. Setting Up Run and Idle Animation in the Animator Controller: Okay, so in this video we're going to be continuing where we left off. We have our player game object with a strike attached to it. So you can see in the sprite render we have frame 0 from the idle animation. So we did properly break up the spreadsheet into separate frames. So now what we need to do is to take the multiple sprite frames and combine them into a animation that can be played by our character so that it can change this dry as time goes on. But before we get to that, we're going to need a couple of components added to our player game object. So first I'm going to hit this little arrow and the hierarchy next to player, so that we're editing the prefab rather than the player instance in this scene. So the original rather than the copy. And we're gonna go over here to Add Component and the inspector, and the component we're going to need is an Animator component. So you can see inside of the Animator component that there are several fields. The one that we care about right now is the controller, or more specifically the field for a runtime animator controller. So we're going to need to create a animator controller so that it can be assigned here for the animator for this game object. So in this folder to create our animator controller, we need to right-click go to create at the top menu. And then inside of this scroll down to animator controller. You might also notice animation and animator override controller. So the animator controller is going to contain the state machine that controls how we switch between animations for our unity character. And then each animation is where we assign the frames that are going to be played, how it should loop, and possibly other settings, such as having triggers happen at a specific frame during the animation and then animator override controller, I don't think we'll get into it too much for this. I don't think we'll cover it too much here in these videos. But when you want to basically take a Animator Controller, the state machine here, and replace all the animations and it with new ones, possibly for a different character that acts in much the same way, then you can use it animator override controller to be assigned the animations without recreating the state machine. And you'll see what I mean by state machine and a bit here. So let's create the animator controller. And we'll give it a name. I like to give mine the name, name of the character, and then underscore a C4 animator controller. You can use whichever naming scheme you prefer. And then there's a couple ways we can create the idle animation. One is to right-click, go to Create. And then down here animation. Or we can go up to window animation, animation. And with a character selected that has a animator controller assigned, which we do not. So we can go ahead and assign the animator controller by selecting it and this project window and just dragging and dropping it into the controller on the animator for the game object. And then once we do that, we can select our player in the scene, the Prefab here, and it'll pop up with the notification to begin animating player create an animation clip. So the second way is that you can create the animation clips directly in the animation window. So let's go ahead and do that. When we do that, we'll have the ability to create a new animation file. So I'm going to call this player underscore idle. And the extension is dot nm, which assigns automatically. So we can just hit save here and we'll see that animation pop up. I suppose the advantage of creating the animation clip directly in the animation window is that. It automatically assigns it to the animator controller here. And we can see this animation clip in the animation controller by going up to a Window Animation and animator. So you'll see that the player idle animation is placed here as a state. So wherever we have these boxes and we're talking about a animation state, and you can see that there are transitions that go in and out of different states for playing different animations. We'll get to that in a second. So for right now though, we want to assign the player idle sprites. So I'm going to click on the folder and the project window, double-click on imports pixel adventure, and let's go to main character. Right now I'm using the virtual guy. So you can use whichever character you want for this. And we have the idle animation which is broken up into separate sprites. So I'm going to expand that now. And let's just rearrange these windows a little bit. And I wanted to bring all of these idle frames in here to the animation. So we can do that really simply just by left clicking on the first frame, holding shift, left clicking on the last frame, and then dragging these and to the animation. So you'll see that a property is added automatically for our player game object, that is the player's sprite. So whenever you want to change which sprite image is displaying, you would change the player sprite value. So that's an sprite renderer and then sprite. And if I zoom in here, control middle mouse wheel, you can see that all of the frames from the animation are added in here and they are different frames. So if we want to see that animation be played, we can go back to this scene window. Of course, we're still looking at the prefab, Make sure it's selected and then hit play in the animation window. And we can see the idle animation playing. So one thing that this idle animation is currently playing way too fast. You can see here for samples it says 60, that we'd basically means 60 frames per second. So for this pack, the animations all designed to play at 20 frames per second. So we just need to change this from 60 to 20. So changing that end there. And now the animation plays much more like we would expect if we look closely. There's one more setting that I really should have changed in the first video, but we can edit it now. And that is the compression for our pixel art. So you can see here that as the animation plays, that some of the colors get discolored, that's not how it was originally meant to display. And we can correct that by selecting all of our images inside of the folder, all of our sprites. And then we go down here in the Inspector to where it says compression setting and change it from normal quality to none. And then it apply. So for pixel, we don't want it to compress it any way. We don't want it to filter in any way. We want it to render the pixels exactly how the artist designed it to display. So just make sure that the compression is set there to none and a should start looking correct. So now we can go over to the Animator window. We can see that the entry point for our animation controller is to go right into player idle. That's probably what we're going to want for most characters in our video game. That's probably going to be what we want entering into the idle state before any actions that are taken to change it to something else. So one last thing we will do for this video is to create a run animation clip. And then in the next one will actually work on transitioning between the two and allowing our character to move properly. So in the assets for virtual guy, we have the runs sprite sheet. You can see that there's no kind of play button next to the run sprite because we haven't actually separated it into separate sprites. So we need to go into the sprite editor. And then when we're here, we need to slice it by the number of columns. So we can do that really easily. Just count the number of sprites here, 123456789101112. Okay, so that means we have 12 columns. Let's go to slice and change type from Automatic to grid by cell count. I think doing cell size by 3232 would also work but cell count, so we change the columns to 12 and forest sprite sheet where everything is separated properly by 3232 pixel squares like this. We can also go to grid by cell size and change it 32 by 32 and you'll get the same results here. But it does depend on if the sprite sheet is separated properly, where everything is separated by the same amount of space. Either way you want to do it is fine as long as this brights are in the right location. So we can go ahead and hit Apply. And now we can close that out. We have our R1 sprite frames, so we can click on player. I'm going to open up the animation window by hitting control sick. It's just much faster than using the window. And we can click on the drop-down where we see Player idle for the animation clips that exist in this animation controller and then hit Create New Clip. So next we're going to want player underscore von, save it. By default, it's going to save in the same folder. So that would be the characters folder here, so we can see Player on. And next we just needed bringing in all of the frames for the run animation. So let's left-click on the first one. Hold Shift, left-click on the last one, bring them in to the animation window. And yep, pretty much done there. So we're going to want to select the player and the hierarchy and hit play. And we can see our character running away too fast though, of course, because every animation in this pack is meant to play 20 FPS. So I'm gonna change the samples to 20. Hit enter, and we have our bond working. So now we can switch from R1 to player here. And we can see that we have two different animations set up on our character. However, if we go to animator, we'll see that there's no proper transition between player and r1. So this is going to get a little bit more complicated because we're going to need to introduce some logic to our character. But for right now, we showed have to animations playing properly, idle and then run. So that's gonna be it for this video. Hope you guys are following along well so far and I will see you guys in the next one. 4. Controlling Animator Transitions through Player Input Script and Animator Parameters: And the last video we set up our Nirvana and idle animations. But the problem is now that we need to be able to transition between them inside of the animation controller. And in order to do that properly, we need to get some input logic in a player input script. And then what we'll do with that logic is to feed it into parameters here for the animation controller to use, so that it can decide when a character should transition between two different states, such as idle and run. And this case, the obvious transition is going to be they were trying to move the character left and right. So if there's no movement input, that character should idle. And if there is movement and put that character can run, we can either do this really two ways. We can test if there's input at all, and that will determine if it's run are idle or we can check the velocity of the rigid body object that we haven't created. Basically is the character moving an actual game space for this video will check whether this input, rather than checking the velocity, depending on which way you do that, it'll give you a little bit of a different feel for your platform, a character. So we're not going to mess around in the Animator window right now. We're going to get the input on a player script. So I know in advance that we're going to need a rigid body component. So first I'm going to make sure we move into the prefab for the player. So it applies across all instances of the player. So for right now, we're going to need to create a player input script. So I'm gonna click Add Component and I will type in here the name of the script we want to create. So in this case, I will call it player input. Pretty straightforward. We'll do New Script, create an ad just so you know, this player input script gets created in your assets folder later you might want to move it into somewhere else, like creating a folder for all of your C sharp scripts or something like that. Or you can put it in characters if that makes more sense to you. So let's go ahead and open up our player input script. So I'm going to, is I'm going to click on the three dots and then do edit script here. So just so you know, I'm using Visual Studio Code as my editor for the C-Sharp code, you can use anything that works for you. This is just what I prefer to use. So let's go ahead and start working on our script. So inside of our player input script, the first thing we're going to need to do is to get access to the Animator component that is on our character. So there's several ways to do this, but I wanna make sure that we select the correct animator component manually inside of the Unity inspector. So I am going to put in here public so that we can access this field and then animator as the type of field we want to find. And I will just call it animator and semicolon to complete our line. So now if we go back out to unity, wherever we have our player input script, we now have a field for an Animator component. So we can click on this little button here, and we can select the animator from the player object. You can also left click hold and drag this field over here so that you are directly dragging and dropping that in. So now we're going to have reference to this Animator component and we can set some variables on it. The variables we're going to want to set is going to be the x move, basically whether the player is trying to move left or right. So we're going to want to get access to the input values in Unity. So I'll put an input dot get access. And then we need the access name, which I know is horizontal. So I'm going to type that in here. And we're going to assign this to a float variable. So Float. We could call it move x if we want. And then we just assigned the float to whatever value we get back from the input dot get access. So to know what these fields are called, Why is it horizontal specifically? That is N side of the Unity editor. So if we go to Edit and the Unity editor and we go down here to project settings, I believe. Then we can find an import manager axes. And you can see horizontal axis has the name horizontal. So that's why we use this string to get access to this value. You can also see the key bindings that are set up for that access. So left arrow, right arrow, or a and D on the keyboard work for that. Inside the Input Manager, you can also see lots of other actions that can be pressed down, such as jump. So jump. The buzzer button here is being set to joystick button three. So later on we'll probably make this something like Spacebar it, but I will leave it alone for now and we'll come back to that later. So just so you know, whenever you want to change your input key bindings, you can do that in here and the input manager. So let's go back to the script here we have the move x in Port, get access value. Now, depending on the perspective of your game, you might also want to get the vertical axis, but because this is a platform, a character we move vertically by pressing up and down, but rather what we would do is it jump key. So I'm not going to bother getting move y here that we would just do import dot get access vertical if you needed to do that. So the next thing we're gonna do is to assign the animator value for the move x. So animator dot set float because that's the type of value where setting, and we're going to call it remove x and then the value move x. So right now it's incredibly simple and won't actually move the character, but it will give us the value that we can use the animator to change the animations. So let's go into, so save the script. I'm going to close out of the animation window. And I'm going to drag the Animator window down here so that we can see the scene and the animator at the same time. And next we need to create a float value for the move acts as a parameter in the animator. So if you just tried to set this value here to move X10 parameter had been created, I think you would get an error. So we need to go in here and do plus float. Oops. Okay, I'm going to have to delete that. N't miss click and then du plus float and then give it exactly the same name. So if it's move x and here it also needs to be move acts in your code. And now we need to use this parameter to control whether the player should run or not. So I'm going to right-click on our player idle state, make transition, send it to player R1, and then we'll also make a transition back Player one to Player idle. So when we're making the transition between idle and run states, we're going to need a condition added to it so we can hit the plus arrow here, and you'll see move x pops inside of here. And we can set it to greater or less than 0. So one way to handle this would be to basically have two separate transitions. One for a mu of x is greater than 01 is moving in the positive or right direction. And then another transition where we check if it is below 0 when it's moving in the leftward direction. So regardless, we're going to need this move x variable eventually to get a sense of how far to the right, the joystick the player is pressing or the arrow key and that case, which would always be set to one I believe. But in any case we are going to need that move x phi. But a simpler way to check if the player should move from idle to run is going to be to use this move x value in the code to generate another parameter, in this case a Boolean variable. So this is going to be called, is moving. And if the character is moving at set to true, otherwise it's set to false. One of the advantages is that by having this determined by code that we have separately and the player input, that we never really need to worry about how it determines is moving inside the animator controller, but we just need to worry about it here. Set that value when it's appropriate here, and then the animator controller will do the rest. So rather than using move x for the condition I'm going to use is moving. So is moving set to true, puts it into R1. And then from Ron to idle, we do is moving equals false. So here it's simplified and really easy to understand. And we just need to determine the true and false states inside of our player input code. So back in the player input code, we're going to take this move x value and will determine a new boolean. So we'll call it Boolean is moving. And what we'll do is we'll check the value against what we consider to be moving and what we consider not to be moving. So I'm going to use the math F function library. And we're going to check if the move x is approximately 0. So move X and then compare that to the float value of 0. So what we're saying with approximately is that if it is moving the tiniest bit to the right, we're just going to exclude that and we're going to say that it is still not moving. So what we actually need to do with this value here, I think, is to invert it though, because we're saying that if it is approximately 0, the, it should not be moving. But this Boolean value is set to, is moving. So we just need to inverse that with an exclamation mark. So exclamation mark, math F dot approximately move x comma 0 f for the value to compare it to. So in other words, if it's not not moving, then it is moving. And then we're gonna take that value and we're going to set that in the animator. So animator dot set boolean this time. And then is moving, comma is moving the parameter. So now we're mostly ready to test our animations out and make sure that the player import script is working. So if we go over from Scene view to game mode, we might notice one thing though, which is that a pixel art character is probably gonna appear really, really tiny here. So in the case that you guys are using the same pack that I was, pixel adventure here. We can open that up and go into the character that we want to edit. So if you click on any of the sprites, CLC pixels per unit here is set to a 100, which would mean that you would need a character to be a 100 pixels to be one unit of game space inside of Unity. And if we go back to the main seen here, you can see that one unit is one of the squares. And, and our character just looks really tiny by comparison. So one thing you could do is to change the pixels per unit for all the sprites across the game. But another option might be to go to your main camera and to decrease the size. So I'm going to drop the size down from five to one here. And so if we go to game view now, our character appears much more properly represented on the screen. So another thing that I'm going to add in to our camera component is going to be called a pixel perfect camera. So I believe this as default in unity these days, but to make sure you have it, you can go up to Window Package Manager and then make sure that the 2D pixel perfect package is included in your project. So having this script added to your camera is going to help ensure that your pixar at games look correctly as your characters move around the screen. Okay, so now we can go ahead and hit play enter Game Mode and start testing our animations out. So inside of the animator, if we click on player and have that selected, we can see that the player idle state keeps looping its animation. Let's bring this down here next to console so that we can see the animator and the game view at the same time. Now if I hit left or right or a and DMI keyboard, it's going to start receiving movement input. Well, first I have to actually be selecting the game view and then you can it left and right on the input. And that value is going to be assigning as a parameter and the Animator. So you can see x move and is moving here. Note that the move x value takes a second to get up to its full value of 1. So if you like that, you can leave it like that with get access. So as long as we press left or right or a and D on our keyboard, we can keep the character and the run state. And if we let go, it's going to return to the idle state. One thing to note though, is that because we're using get access instead of get access raw. At the moment, it takes a second for the move x to go from 0 to one or 0 to negative 1. So if we use this as a multiplier value to figure out how much force we're applying to the character, then we can kinda have the movement accelerates over time. That might be something you want or as an alternative. Let's go ahead and get out of play mode here. We can switch to get access raw. So get access ron and sad of get access horizontal. So the name of the field still the same. The difference is now that when we go into play mode and then we hit left and right, it instantly goes to move of negative one or 1. It's up to you whether you want the character to accelerate or just instantly reach its maximum velocity. Now, another problem that you might notice is that it takes a little bit of time from when you press the key to actually switch to the animation state. That's because our transitions currently have exit times. So we can actually edit these wall play is running, which is quite handy. So if we click on one of these transitions, you can see Has Exit Time is checked, we can also expand settings and see the transition duration is set to 0.25. So the transition duration is how long it takes to move from one state to the other state. And then the exit time is how far into the state do you need to be in order for basically idle to run transition to occur? We want the character to be able to transition at anytime. So we're going to uncheck has exit time. But then we also want the transition to be instant. There shouldn't be any kinda inbetween here. So I'm going to set the transition duration to 0, and I'm gonna do the same thing for the run to idled transition as well. Uncheck has exit time and sat transition duration to 0. And now if we use left and right to control is moving and move x, you'll see that it changes instantly. For most 2D platformer games, this is probably going to be what you want so that the controls feel much more responsive. One other thing I want to change the background color. I really don't like the solid blue that comes default and unity. So I'm gonna change the background to maybe something more like a very dark blue black for now and hit play. So I just think this looks a little better for right now. It also contrasts our very bright sprite as well. So I think that looks pretty good. Now, there's a few things we need to add to our character, which will be the next video on being able to make it actually move. First off, we need to have it have a rigid body, which is the physics component, which allows a character to move, to receive forces. And then we're going to need to actually add a force to it and script, but rather we're going to add a behavior script to play a run so that it can move but only when it is in the player around state. So that's gonna be it for this part. I hope you guys are following along well and I will see you guys in the next video. 5. Building Ground on a Tilemap to Stand On: So currently we have a character with idle and run animations, however, were not able to move the character yet because it has no rigid body component and we're not adding any forces to that rigid body. However, before we set up the rigid body, we should actually add some grounding. So I'm gonna be using the pixel adventure pack to set up some basic tiles. And then in the next video we'll add the rigid body. We're doing it in this order because if we add the rigid body without having tiles or ground beneath a character, it's just gonna fall off the screen and that'll be a mess. So let's go ahead and add some tiles to our game. So inside of the terrain folder for pixel adventure, in which we grabbed at the start of the series. You can see that they have a bunch of different tile sets for creating levels. So what we're gonna do is change the sprite mode from single to multiple, the filter mode from the linear to point, and the compression from normal to non. Having the correct settings here for a pixel art game. Next, I'm going to go into the sprite editor and we're going to slice all of these by the cell size. So we can see by the name of this file that is 16 by 16 for each square. So I'm going to put it in pixel size 16 by 16, slice it. And we should get a perfect slice of all of the tiles that actually have some pixel information there. Note that unity ignores the places that have blank space, which is handy because those would be useless tiles. So let's go ahead and apply here. And now we have all of the sprites squares that we can use as tiles inside of our game. So to create a tile map, we're going to right-click in the scene hierarchy, go down to 2D object, tile map. And then that's going to add a tile grid. Let's see if we can double-click out for that. And yeah, if you're looking at grid and then layer, you can see that there is a tile grid here now. So currently for the game, everything is set at a 100 pixels per unit for the characters. And this is like a 30 by 30, the pixel sprite. So of course it's much smaller than an actual game unit. So once again, you can change your sprites and the pixels per unit to a lower value like 16 if you want them to appear bigger. Another option is to go into the grid and then change the cell size to reflect the size of the tile squares. So in this case, it's 16 pixel tiles, a 100 pixels per unit. So we want 0.16 for the X cell size and 0.01. six for the Y cell size. And now the squares should be much closer in line with the size of our character over there. If we click on tile map now you won't see any area to really edit the tiles and take those sprites and put them in. It's actually a separate window. We need to go to Window and then C, and then go down to 2D tile palette. And we can put this somewhere. I like to have it next to the inspector. So we need to create a tile palette. And then using that we draw onto the tile map, which is inside of the grid. So let's go find the terrain here. So right now we're in the Tyrian folder. We need to create a new pallet and the tile palette window. So let's go ahead and give it a name. I'll call it pixel adventure tiles. I think we can leave the cell size to automatic for right now, though, I'm not sure if that needs to be changed. We'll see what happens. And let's just save the tile pallet inside the folder with the, our assets here. And so now we need to give a place for the tile pallets. You could put it in the folder where you imported the art assets or you can create a new folder for these kinds of things. So I'll just create a new one for now. I'll call it pallets or tile palettes, and then select that. Okay, so now we have pixel adventure tiles which exists in that pallets folder. And we can drag this entire sprite sheet with all of its items just by grabbing the original image. And if we drag this onto the grid here, it's going to, it's going to try to automatically generate tiles with the exact same placements as that sprite sheet. So once again, I guess I will put it into the tile pallets folder. I'll create a new folder here called tiles because it's going to create a lot of files. And we can organize it a bit more later, right, let's select the folder there and you should see all of the items being imported into this palette. It may take a while in this case, because there's actually a lot of them. You can see 144 squares or tiles being created. And we can see the sprite sheet imported correctly here. Now if we go to Selection mode, we can click on any of these tiles and then we can paint onto a tile map. So this is gonna be really handy. We can zoom in mixture, you're on greater tile map, and then we can go into Paint mode with tile pallet. So that's the paint brush over here. And you can start drawing with any of the squares that you want, I guess are used these metal tiles with the darker color here. So I'm just going to left click hold, drag it around, and paint some tiles onto the scene. We can also switch to a different square. So this one which sits above is going to be used for the top tiles. This one on the far right, for the corner edge on the right, and in this one for the left corner, we also need to use these for the left edges. You can see how there's that black outline. So that is important. Otherwise it won't look right. And then this is the bottom right corner, this is the bottom left corner, and then this is the bottom. So by using these tiles, we've created a simple platform which are character can stand on. Now. Right now, there's no collider for these tiles. So if we were to add a Rigid Body collider to our character, he would simply fall through them. So we need to go back to the inspector for the tile map and add a new component called a tile map Collider 2D. So tile map Collider 2D. And once you add that in, you'll see that there's now a square drawn around every single one of these tiles. And just like that, the collisions for the tile map are going to work correctly as long as the character is also setup, right? So in other words, we have ground that we can stand on. And worth noting here, if you wanted to create tiles, possibly background tiles on a separate tile map, then you can just create a tile map and not add a tile map collider so that a character can move through them because you want to want the background to block a character, but you wouldn't want to add some background into the scene more interesting. So just know if you want it to interact with the player, have a tile map collider, otherwise you don't need it. So that's gonna be it for this in-between video on setting up a simple tile map inside of your Unity project. And the next one will setup the platform or rigid body. 6. Movement Scripts & Dynamic Rigidbody: Now that we have ground, the Arab character can stand on thanks to the tile map collider that we created in the last video, we can go ahead and add a Rigid Body to our character and have him fall to the ground. So let's do that as well as setting up the left and right movement for our character. So on our player gameObject, I'll go into the Prefab here with the arrow button and let's add a Rigid Body 2D to our character. So we're going to leave it in dynamic mode. What it means by dynamic mode is that it's going to take full advantage of the Unity physics engine. You apply forces to the rigid body and then unity calculates the rest for things such as what that character should collide into, where it should stop sliding along the ground or edges. So in dynamic mode, it's much easier to move your character along properly without it getting stuck. There's also kinematic mode, which you manually move the position of the character encoding. And the problem is then that you have to set up collision detection and do all of that manually. So kinematic mode tends to be a lot more work. But if you wanted the character to interact with physics in a way that isn't standard, then you might want to switch to kinematic mode. Personally, I would think more on using it for things like a moving platform where it doesn't move but not in the standard way a character would. And then there is static body types for things that never move. For instance, a good example of that would be the tile objects down here. Now, we don't attach a rigid body to the tile map directly. But if we add a rigid body for each square, it would be in static mode because they never move. So we have dynamic mode set here. There's a few options that are going to be relevant for this series. Linear drag. When you want a character to slow down faster, you can increase the drag. It's similar to having friction, except it also applies in the air at all times. Basically, whenever the character is not moving, the higher their linear drag, the quicker it's going to return to 0 velocity. And then we have gravity scale down here. So in Unity, they have gravity applied at negative 9.81 units. So we can see in the project settings physics, 2D, gravity. Why negative 9.81. So the gravity scale here is like a multiplier on that. So if you want normal gravity, you would have the gravity scale at 1. If you want it to be more like moonwalking, where the gravity doesn't affect the character has strongly, then you can load the gravity scaled down further. Or if you want it to be effected by gravity more so you can increase the gravity scale. So if you have a very floaty character, having a lower gravity scale might be interesting. The other thing that's relevant to us right now is going to be constraints. So n constraints. As we apply forces to the character, we can limit what directions it can move. So freeze rotation is going to be important for a character that stands upright. Because imagine there was a force coming at the character from something like the top right, and it was pushing at it from here. We wouldn't want the character to roll like a ball over the edge. We would just want to push it back but not rotate it. So for a platform of characters, you're probably gonna want freeze rotation assigned with z mark checked, ok. The other thing we're going to need is a collider attached to this character. So the rigid body exists, but there's no collider to detect when it collides into anything so that it can or interact with physics engine properly. So we need to Add Component and pick out a collider. So I think Capsule Collider 2D is going to work really nicely here. So when we add that, you can see we have something of an oval shaped. The difference between a capsule collider and circle collider is that it doesn't need to be a perfect circle. It can be any oval shape. So let's edit the collider here. And then I'm going to bring these edges in. For left to right and top until it fits our character significantly better. So looking at this, it's a pretty good representation of where our characters body parts would be. Good enough for our 2D game like this anyway. So let's turn off edit collider. And you'll see here that I have a plus mark assigned to the capsule collider because I'm editing this on the copy of the prefab, not the original. So I wanna make sure that this actually applies to the original as well. So I'm gonna click on these three dots, go to Add Component and choose apply to prefab player. And whenever you see that plus sign, that means you added something on from the original prefab. And you can also have minus for when you've removed something that the original prefab hat. So we're leaving Is Trigger off because this collider is something we want to use directly for basic physics and the game. You can also have trigger colliders when you want a zone that objects can enter but not collide with. But we are wanting this to collide. We want the rigid body to be able to collide with the ground so that it stays there. So let's go ahead and hit play now. And probably the thing we're going to notice is that the gravity is really, really fast here. So I can move my character up here. And then when I play you'll still see a hits the ground very, very fast because the gravity is set to a 9.8 units, right? Each of the units in the game right now are really big compared to the size of the character and the tile map here. And I think I actually want to change that. I've been mentioning it a few times, but let's actually go ahead and correct it so that the character is more like one or two units big, rather than a fraction of a unit. Having it to 100 pixels per unit is nice and a sense that you know that every 0.01 is one pixel. But I think I'd prefer it the other way. So I'm going to click on our assets such as this terrain. We added it, and I'm gonna change the pixels per unit to 16 and hit apply. So that means that every square we draw from the palate is actually one unit Endgame. So we're gonna change the grid size to one because one unit is now 16 pixels for this background terrain and also change it to one for cell size. So now you can see that our tile map squares perfectly line up with the grid. Every square is one unit and maybe you find that makes more sense. We can also go to the player sprites. So in virtual guy, I'm just going to select all of these and change the pixels per unit to 16 and hit apply. And our character should get much, much bigger. So since we're scaling everything up, we also need to apply that to the camera. So with the camera, I might make the size five or so. And for the pixel-perfect camera, at pixels per unit, we also want to make that 16. So the important thing is that we're consistent. So for using 16 pixels for our Pixar, we should probably just use that for all of the art we bring into the game. So if we do that, we can see in game mode, it renders pretty nicely still. And we can play. Let's go ahead and do that again. And you can see that the gravity is now much more reasonable at its negative 9.8 units, though, you can also go up to Edit Project Settings and customize the gravity so you don't have to reduce the pixels per unit. You could just lower down the gravity it whichever way you like it. So let's check out our player once again and we can see that the capsule collider is now way too small. So we're going to just need to edit the capsule collider. And let's actually do that on the prefab. So clicking on the prefab arrow and the hierarchy, this would just make sure that all of the edits propagate across all copies of the character. So let's go ahead and set these bounds here. So left bound, bottom bound, and top bound. The one that's probably going to be most important is the bottom bound. We're going to want to make sure this lines up really nicely with our actual pixels. So something like that. And I might manually adjust the sizes here as well. So this is almost negative 0.206. So let's put it that, that this is 1.37. And we're going to have the offset of XB 0 of course, and then the y 1.48. And I think it's just a little better to have more precise numbers like that, so it's a little more readable. Okay, so now we can go back to the scene. We can see our capsule collider fits our character properly. And if we at play, he should fall to the ground smoothly and land right on top of it. And that's what we want to see. Okay, so I think the last thing we need to do for this video is to actually add left and right movement to our player. Now we could write all of that into the player input script. But as we build a platform, a controller with many different states, if we try to cram all of our logic code into one player and port or player movement script. It's going to get kind of messy. So what I like to do is let's open the window animation. Animator here is for the states or sub-state machines. Sub-state machines being a state machine within a state machine, you can actually add behavior scripts to those states. So what you can do is only allow the character to move when it's in the run state or any state that has the same script attached to it. So you don't need to do logic checking directly in the scripts for whether it's on the ground or not. Because you would assume that by entering that day and being in the state that you're either code has already determined that it should be in the correct state. So all you need to do is assume it's in the run state, so it should be able to have these behaviors. And by separating it into these little scripts, I think it's just a little bit easier to go through your code and figure out where your problems might be. For instance, if you're trying to figure out why there's some weird behavior in the run state. You just need to go to the run state and look at all the behaviors that are attached there, and look through that rather than all of the code that applies to your player. So let's go over to the player script though, and we'll add a little bit more into the player input. So I'm going to edit this script here. And now of course, there's gonna be many different ways that you can do this precisely. But what I'm going to do is have the behaviors on the state machine, edit the values, the parameters of that animator, and then end this import script. I'll just take those values that the behavior scripts manipulated, take them and apply them as a force to the player. So the, for instance, was to apply here, but the logic on how we get to the values which should be applied as a force exists within those behaviors states. Now once again, I'm not sure if that's the perfect way to do it, but it's been working for me. So. We'll go with that for now. So if we're going to want to do anything physics-based, we're going to want to do that on a fixed update and stat of just a normal update function. So fixed update works at a certain number of times per second. I think it's at 250 per second by default though that isn't editable value. And the idea is all of your physics updates are going to be run the same number of times and this helps to make them more consistent. And it's recommended that all of your physics processes apply the same number of times per second. And having everything that is physics-based B and fixed update is how you guarantee that, because fixed update will run as fixed number of times per second. Okay, so what we'll do in avoid fixed update is get values back from the animator parameters. So I'll do get float, and I guess we'll call it force acts. So this will be the amount of force that we should apply to a character over 1 second of time. Of course, when we're applying this in fixed update, or do it multiplied by Time.deltaTime. And we'll also get another value called impulse y. So this will be for jumping. When we want to apply a force as an impulse, everything gets applied at once and time is independent of that. So that's why I'm going to call this impulse and that force acts. So you might notice we're getting a lot of string values here. String values do need to be precisely consistent across our scripts. So what I found is a pretty handy idea is to actually store the string values in a separate static class and then reference that same static class from both our player import and all of the behavioral scripts that we're going to attach to this different states and the state machine. So let's go ahead and do that. So I'm gonna open up assets and I'll just put this in the default directory for right now, right-click New File. And then I'll call this PAP player animation parameters. You can call it whatever you want. It's just going to be a easier acronym to reference than typing out the full text at once. So PIP dot cs, and in here I'm going to give it a public static class, PAP, then go with the brackets. So I've added a little comment here, player animation parameters. So for any parameter that we're going to put into the animator here, we're going to want the name stored as a value here. And then if you need to make sure that the value in here is the same as here. You only need to check one file rather than every single file. So let's start writing down some variables. I'll do public constant, move x, and then we'll give that a name, move x, and then we'll do public. Oh, well, we also need to give them a type. So public constant string, public constant string is moving, equals is moving. And then let's grab the other values from here. So we could make this a string, the axis name. So I guess I'll call it axis x, end quote. And that'll be the horizontal perimeter. So let's see anything else where you can rename. We have move x, we have is moving. So let's add in force x and impulse. Why? So public constant string four x equals four x. And then public constant string, impulse. Why is impulse y? So now what we can do is reference this class. So I'm just gonna replace all of these hard-coded string values with our new class. Okay? So I want to make sure that this is actually picked up by the Unity project as well. So let's click back into the project. We should see the asset database refresh here and make sure that the file is in here, PIP. So let's go back into player input and see if we can reference that. Okay, so PIP, and now we just need to put the variable name. And anytime we change the variable inside of that player animation parameters class, It's going to be updated across anywhere we reference it. So change once fixed for everything. So let's see player, player animation, PIP dot axis x input. And then here we'll have PAP dot move x. Pap dot is moving PAP dot for sex, and then PAP dot impulse white. Okay? And now we've cleaned up all of our hard-coded strings and we only need to edit it here if we ever need to edit it again. So in fixed update, we're going to get the force x. We need to set that to a variable. So I'll just call it float for us, X equals that. And then we'll do float impulse, y equals animator dot get float impulse. Why? So I guess we'll say if impulse y does not equal 0, then we'll apply it to the rigid body. So to do that, we need to get the Rigid Body. Of course, let's do a void start and then up here, or do private Rigid Body 2D, rigid body 2D RB for rigid bodies, semicolon and then RB, and then down in start RB equals get component, Rigid Body 2D. As long as there is a rigid body attached to the character, which they should always be. Then we'll get that here and we'll use it in our code down here. So we need to apply the impulse Y to the rigid body. So we do rigid body doubt, add force. And it's a vector too. So we're creating a vector two with the flow in the y. So it's going to be 0 for x and then impulse y. And then we need to add comma and change the force mode two D, two impulse, okay, and then semicolon at the end there. So very similarly for forest x, pretty much the same thing we can do if force x does not equal 0. Then RB add force. And then we'll have a new vector two here with force x and 0 for impulse. Why? And it defaults to force mode, force. So we don't actually need to have that extra parameter there though. You could put it there if you want. Now if in this script we ever want to get a y force that isn't a jump, then we could basically do the same thing, animator dot getFloat and then add that to the vector here as it adds to the character on every frame. But in this series, I don't think we're going to actually have a constantly applied force why? Iowa jumping is handled by impulse and I think that's all we need. But what we do need here for the ad force is to actually multiply it by a time. Delta time, this force is being applied over time. So we need to apply the right amount of force for the duration since the last frame of time, just in case they're inconsistent and in fixed update, Yeah, it should be consistent. They should all have this same frame time, but just in case they're not, this guarantees it. So that's gonna be it for our movement. And we just need a script that's going to set this force X value properly. And then this will pick it up from the animator. So let's close out of this and go over to our Animator window. And now we need to add in the extra parameters that we created. So I'm going to add a new flow, and this flow is going to be force x and then add a new float impulse y. And we can also just verify that those are the correct names by going over to the PHP file once, just make sure that they're the same year. That's the only verification you'll need to do. Okay, so now I guess we just need a behavior script that depending on the input which we feed in, which we have already done, move x set here. Then we can set a force that the character should apply in the x-direction overtime. So let's add a new behavior script. Because we might reuse this for other states that aren't run. I'll call it player, horizontal movement and maybe behavior at the end to specify that it's meant to be in these state machines as a behavior file. And we'll create a new script for it. So let's create an ad. And now we can edit the script. So inside of a state machine behavior, you're gonna get a lot of these over-read and functions that may look a little different from your standard mono behavior script. So these are really handy because you can have certain things happen as the character enters a state, leaves a state or stays consistently within this state. So for instance, if you had a state where you wanted to stop movement, you could do that with on-state enter. So in this case, what we're going to need to do is to control the force x that should be applied to the character. I think we're going to need it to set to force x equals 0 at the end here on state exit. So on-state exit, what we can do is set the force x equals to 0, so that once it exits this state, the force should no longer apply to the object. So let's say animator dot set per set float rather. And we'll give it a rather than the string name. We can actually use PAP here. So for x, and then we'll set the value for that to 0. Ok, so you can see the handedness of having your strings in another file like this. We don't need to remember what we called it because we can just reference the variable rather than the exact string. Okay, now let's do on state update. So on-state update, we're going to want to get the import move x that the player import set on the animator. And then we just pull the value for that. So let's do animator dot getFloat enrolled a PHP dot move x. And we're going to set that to a variable value. We might actually need to reference it outside of the function later. So let's do float, move x. And then we can set that to the value we get back from the animator. Next, we need to figure out the amount of force that we are going to be applying. So let's go ahead and make a public. So let's go ahead and make a public speed variable for the characters run. So public, public float ruins speed. And I don't know how it's gonna turn out. Let's just default it to ten and then we'll edit it as we need. So what we're going to do is to set the new force x value. Okay? So the move x value can be anywhere from negative one to one here. Because in the player input we did get access Roth, the value should immediately jumped from negative one to one on a keyboard. As soon as we press the key down, if we did get access, it would accelerate to those values over time. But we can just change this to get access if we ever want an acceleration style movement rather than a constant movement speed. So let's actually just multiply in here by the value it's actually set and then store that as the force acts. So let's do animator dot set, float, and we'll do PIP dot. X is going to be move x times the run speed and semicolon. I think that might actually be at, okay, and then this move x, we're going to pull that in here, getFloat force x. And then of course, the code we created is only going to run when it's in the play or run state. Now, we don't have to put it directly on to play around. We can also have like a ground state for instance. Okay, so let's go ahead and test it now. So play mode, we hit left and right. So I think what might be happening here is that the running speed is set way too low. So I'm going to try bumping that up to 200 or so and let's see what happens. So I hit play. Okay, and now we can see the character is actually moving, but very, very, very slowly. So let's make that at 1000 and the numbers are pretty much arbitrary. Let's go to play here. So that's probably a lot closer to what we want, though. I would say that character is sliding around way too much. So this a couple of areas we can change things for where a character should slow down as it stops moving. One is linear drag, and then the other is physics materials. So in physics materials you can add friction and that can be on the grid as well as the player with linear drag. However, if you increase it, it will in fact drastically increase the rate at which the character slows down, as well as reducing the impact that the force has on the character to begin with. But that also applies when it's in the air. So that might not be what we're looking for. So I'm going to exit play mode there. And what we'll do is try adding some friction to the tile map. So physics materials are really simple. We can create one inside of the root of our project. I'll do it in a folder. I'll just do create folder. And let's just call it physics materials. Why not into the folder? Let's right-click Create. And then let's do physics material 2D. So you can see by default, friction of 0.4. bounciness of 0. We don't need bounciness because the character isn't going to bounce around like a ball. So let's see what happens when we actually add the physics material to our character. And we could just call this player physics material. Okay, and also right-click and apply it to the prefab. So let's hit play and see how that changes things. Okay, so not too much yet. Let's go to the tile map and let's also add in a new physics material here. So physics material 2D, and I'll call this standard ground. And let's go to the tile map and we'll add in the physics material. So this also has a friction of 0.4. let's hit play and see what happens. Okay, so we can see still very slightly. But let's go to the standard ground material and make it much higher. So let's try 0.9 now and hit play can also make the player 0.9. So this is the way you're going to have some fine tuning of the numbers. We could add a little bit of linear drag here, though that's also going to affect the air movement. So I don't want to have too much of that. Let's hit play. And this should slow the character down a little bit, as well as the amount of force that really gets applied to it should slow down as well. But it's still very slightly. So maybe I'll just take the friction of the ground and make that much higher. Let's try a value of two. And we're getting much closer to the amount of sliding that we'd actually want it. We can even go a little bit further than that. But one thing I do want to change before the video is over is add a little script so that depending on the direction that character is travelling, we're actually going to flip the direction which the character is displaying around. So an animator, I'm going to left-click here. So on the base layer, I want to add a behavior. And I'll call this player flip New Script, create an ad. Let's edit the script here. And as long as it is in this state machine, what we're going to do is, I guess we're used the move x value for this. So we'll do animator app.get than PAP dot move of x. And then we'll have this assigned to a move x float. And if it's positive, then we're going to have the character facing to the right. If, if it's negative, then it's going to be facing to the left. And so how we can flip the character is by doing animator dot transform local scale. And we're going to set this to a new vector three, and we'll do 111. Elsif mu of x is less than 0. Then we'll do animator dot transform.py local scale equals new vector three negative 111. And before all of that will actually do, if x equals 0, then we'll just do nothing. So this is actually going to become an else-if and we'll move it up there. So we'll just check if move access several. So there may be a lot of times when a character is just idling there. So it doesn't make sense to put that check first and then just ignore the rest of the code if that's the case. If I'm right, I guess that's going to work. So as long as the x values being set, then the character should flip around depending on if it's moving to the left or moving to the right. So let's go ahead and test that here. Play mode. Okay, so we have moving to the right and then left, we move to the left. So the local scales being set correctly and our character flips perfectly. And doing it this way is also good. Because if you flip the transformed, then that's also going to apply anything that's based off of that transforms, such as if you create a projectile that's launching from the character. Well, if you flipped the transform, now it's going to be coming out at the left side rather than the right side. That's the advantage of actually controlling the transform rather than just flipping the sprite renderer, which obviously would work visually, but not when other things depend on the transform. So at this point we have a character that can run around inside of our game. He's a little bit slightly, but that is just a matter of changing the numbers may be adding more friction or linear drag. Overall, our character works pretty good and is affected by gravity. So that's cool. So I hope you guys are still following along well and I will see you all in my next video. 7. Air States Falling, Rising, Jumping, Landing, and Double Jumping: So in this video we're going to be taking our run an idle states, grouping them into a ground state layer. And then we'll also be adding in the area of states which are going to include jumping and falling as well as double jumping. And then in the following video we'll add while sliding as well. So inside of our Animator window we have player idle and play a run. So what we wanna do now is to combine these into one group. And the advantage of doing that is going to be that if we want to add a animation behavior to all states that are concerned with the ground or all states concerned with the air. So we're going to want to take our idle in one layer and group them inside of a sub-state machine. To create that, we right-click on the node graph and go to Create sub-state machine. So I'm going to select this and call it ground. So with the sub-state machine, we can double-click into it and you end up with a state machine inside of a state machine. So just like on the outer state machine, we can add animation behaviors like player flip behavior here we can also double-click into ground and add behaviors at this level. So if there's an animation behavior at this ground level, it applies to every state and side of the sub-state machine. So I'm going to click on the base layer to go back out. And I'm going to take the player idle on player run. I'm going to Control C, go into the ground layer and Control V, paste it in. So now the states exist inside of the sub-state machine. I'm going to take the entry point, right-click on it and make the state machine default state to idle. I probably doesn't matter because the state machine is automatically going to be switching between i, o and move, whether it's moving or not. But this is generally how I prefer to Saturday. So now I'm gonna go back to the base layer. Now we're gonna take the entry point for the overall state machine and set ground as the default. And within the ground state machine, we choose player idle. So when we hit play on the game, I'd always going to be the default state. So now we can get rid of the original play around and player idle, we don't need those anymore because they exist within this ground state. So we can start double-click and see that. So in order to make it so that the player can move as long as it's within this ground sub-state machine and not need to add it to player idle and play run individually. You can see that compared to the previous video, I already have the player horizontal movement behavior script removed here. Instead of adding it to each item here individually, we can just go to the base layer and add it to the sub-state machine, the ground layer. I'm going to add the behavior here and we're going to do player horizontal movement behavior. So let's take the scripts default VLAN speed and boost it up to a 1000 so that our character can actually move properly. I'm going to go ahead and hit play here. And we can see that we can move left and right pretty well once again, and whether we are an idol or the run state, we still have that movement script active. So it allows us to move as long as we're within the ground sub-state machine. Okay, so now we need to set up a way for our character to be able to enter the air. So there's going to be two ways to do that. One is basically falling off a cliff, which is going to go right into a falling state. Or We can hit a jump key on our keyboard or we can hit a jump button which will allow our character to move upwards. So let's go ahead and create a air sub-state machine to handle all of those falling and jumping states. I'm going to create a sub-state machine here, and I'm going to call this air. Let's start by double-clicking into air and we can create a couple of new states. So let's right-click and create a new empty state. And I'm going to call this player underscore falling. And let's create a new state. So let's call this one player jump. And then after we have jump working, we'll also want to create a double jump state which is going to have some different variables set. Maybe you want to play a different animation on the double jump, or maybe you want the double jump to have different values and how much you can jump on the second jump. So, and in any case, it's not a bad idea to create a second Jumps state, rather than just allowing the character to jump twice within the normal Jumps state. So let's pull these down and I'll right-click Add a new state. And I'm going to call this player double jump. So now we need to go back into the ground sub-state machine. I'm going to double-click in there and we need to set some exit points for the states in here. So one way that we would want to enter the air is if the character of basically walks off the edge, so would not be on the ground anymore. So I'm going to take player idle here, right-click, make a transition, and we're gonna go to the exit here. And the condition on this exit is if the player is not on the ground, so is on-ground false. So I already have all of the other variables pre-created over here. So if I talk about one and you don't have it already, just go ahead and add it as a parameter using the same name. So is on ground, and we want that to be false. So if the character is not standing on ground, then it's going to be falling. Now, let's do the same thing with player run. So I'm going to make a transition exit here, and that's going to be, is on-ground set to false k. Now let's click back onto the base layer. Now we need to tell the sub-state machine how, once it's exited from the ground sub-state machine, how it can move over to air. So we're just going to set another transition here. If it's not on the ground, then we're just gonna go straight into falling. So states player falling and as the condition here is on-ground set to false. So for the following sprite, we're just going to be using this fall 32 by 32 sprite, and we'll have a little animation created from that. So back in my Characters folder, we can see I have player fall as an animation. So let's click on the character and then we'll go to Window Animation. Let's see Animation Window. And we can't see it in here because it's actually not assigned to the animation state node yet. So let's actually move this down here. So it's kinda out of the way. Go back to the animator. And for player falling, I'm going to set that animation motion to play a fall. So now if we go to animation, we should see it pop in here. So player fall, just a single sprite. When I was talking about if we hit play, well, that's what it's gonna look like. So I've gone ahead and added some extra terrain here. I'm just going to move this character over here to the left so that we have some way for it to fall off of. Okay, so let's go ahead and test the falling animation. I'm going to move our character up here to the top left. So that we can fall to the ground and then go over to the left some more. So I'm going to play here, character is going to be on the ground and we go off the edge and we do get to that falling state, but there's an exit time associated with that, and we probably don't want that. So let's go back to the animator window, go to the ground state and take a look at these exits and make sure that the exit time is toggled off so that the transition can be ends and when it starts falling. So let's go ahead and hit play now. And this time the character is going to immediately transition into the falling state. But we have another problem which is now there's no way for it to exit when the character is on the ground again. So we need to basically do the same thing in reverse. So going back to the base layer and then air, we're going to want to show the animator how it can land and then transition back to the ground. So basically, as long as it's in the air, if the character ends up on the ground at any point in time, we don't really care what state it is. We want it to land. So we can use this any state node over here in order to make that transition into landing and then to the exit. So I'm going to create a new state here. I'm going to tell any state to go here. And this is under the condition that is on-ground is true. So is on ground is true. So it can enter this state and we're going to call it player underscore landing. And then this is going to go to the exit. I don't think we need to add an extra condition here for the exit because is on ground has already been checked. So after the player's done landing, I don't think we need to check for it again up, so we'll leave it like that for right now. So now we need to give this emotion. So depending on how your sprite character was animated, there may actually be a motion for the player landing a few frames of animation to make that transition look a little smoother. In this case, this character does not have one. So we can actually just have the landing state exist without having an extra motion here. So for right now, we might not need to really do anything with the landing other than allow it to exit back to the ground. But for now, let's actually go ahead and add a player landing behavior. So I'm not gonna do anything with this yet, but I think we're going to need it later on. So just for now, we'll just have it kinda blank there. So at this point, from any state, as long as the character enters the ground, then the player landing behavior can allow it to transition outwards. So let's go back to the base layer. So from the air we want to go to the ground. Let's just say state machine ground. Don't think we need to be more specific than that. Really with this transition, we might as well just tell the ground to go to the air. And then from air, we can actually pick out what the correct entry point should be. So I'm going to change this to be ground to air. And let's do state machine air instead of ground straight into falling. And the conditions here, Let's just set as on-ground is false once again. So the top transition is, is on ground true, and the bottom one from ground to air is on-ground false. So now when the character is back on the ground, it should transition into the player idle here. But we have the ability to change this little entry point if for some reason we ever wanted to have a different default. So let's go back out and see if we can kind of test that out. So when we hit play, the character goes back to the ground here. Let's see where we actually add. So we're getting stuck on the player landing here. The issue is that Any state can transition into player landing and the only condition is that is on-ground is true. So technically player landing is just looping back into play or landing. So we need an extra condition for this to work so that once it enters player landing, that it can't enter player landing again until it comes back into this cycle of being in the air. So let's set up that and the code for this. But we're going to be using a trigger. And in order to enter the landing state, we're going to need this trigger to be set. So as soon as we enter the landing state, we reset this trigger so it won't go back into here. So presumably you don't already have this. So back in the PHP file, you can create a string for this. So public constant string landed on ground equals landed on ground. And we'll use that as the trigger name. So if this code is going to reset that tricker than we need a place where the trigger is going to be set. So back on player input, we need to have a few checks in order to set that landing condition. The landed on ground tricker. So we're going to be checking for two things. So the first condition we're going to check is whether the on the last update cycle, the character was on the ground. And we do that by using animator dot get bool, PAP dot on ground. Essentially checking if it was already on the ground when we go through this update function. And then we need to check if on this update cycle, if the character is already on the ground. So in the last videos, we should have already had this bet. So now we just come in here and we take those conditions and we determine whether or not it qualifies as the character having landed on the ground. So if it wasn't on the ground before and now it is on the ground, then presumably we are in the air and then we hit the ground, so we're landing, so we have to set that trigger. And since we're using parameters of the Animator, we have to make sure that that parameter is once again set on the animated parameters. Down here we have landed on ground as a trigger. So this is going to be when the character hits the ground and that's going to be unset as soon as the landing consumes that trigger. The last thing we need for all that to work is just to add a secondary condition from any state to play or landing. So we're going to be checking for that landed on ground trigger the is on-ground check here might actually be redundant. Landed on ground kind of already implies that. But let's just leave it there for now, and let's make sure this works. So we should be able to now transition back onto the ground. Okay, so let's go ahead and hit play. And it should be working now. So let's go ahead and hit play real quick. It's going to start in the falling States since the characters aboveground. And then it's going to transition into landing and then back to the ground. So now you can see that the landing only happens once because that landed on ground trigger is required in order to enter the player landing site so we exit the air properly. And now we can move around left and right as we desire. And if we go off the edge, you may notice that our character can't control its movement anymore. So we have the option of adding the player horizontal movement behavior to the air as well. So this is going to be kind of more of a preference point. Do you want the character to be able to control its direction watts, and the air. So if you do. Then we just go out to the base layer, click on the air layer, and let's add a behavior, play a horizontal movement behavior. So on the ground we have it set to 1000, But in the air we may only need it to be something like 300. So our character has friction with the ground when setting this dynamic rigid body mode. So in order to move the character, you need more movement power on the ground than you would in the air, because the air is not going to have any friction or air resistance by default. So let's go ahead and hit play. We might just need it to be at 300 or perhaps even less than that. So if we fall off the edge here and the air, but we can still move left and right if we want to control our character. So maybe we want a little more than that, could set it to 500, okay, and then we go left and right. So, so you can kinda determined for yourself how much run speed you need and the air. You can also rename the variable if it doesn't make any sense for it to be run speed when you actually are in the air as well. But you can reuse the same script. And multiple states are multiple sub-state machines and just change the values on it if you want it to behave similarly, just with different values in terms of its power. Okay, Now we need a rising state and we need to have scripts for the jump and double jump. So let's do the simplest 1 first, which is going to be creating player revising. So I'm going to right-click on the graph and air. So create an empty and we're going to call it player rising. So when you would want to play the vising animation is when the characters velocity is going upwards and it should be following when it's going downwards due to whatever forces are acting on it. So gravity would be the obvious one, but in your game, you might make it so that there's other actors that could change its velocity, such as running into a projectile and it actually affects your character's movement as well. So with player rising here, we need a motion. So I'm going to use player jump here. So if we take a look at the character art and let's go to virtual guide here. So we can see that the jump animation is actually just a single frame of the character moving upwards. We can use that for the jump promotion, but also for the rising motion. So with player rising, we're going to assign player jump as the motion here. If we click on our character and we changed to player jump, we can see it's just simply setting that single frame. If we hit Play, we can see our character showing the vising state or the Jumps state. So now we just need the conditions for when it should switch between rising and falling. Super-simple just going to be looking at the velocity y here. So I'm going to make the transition to play a falling and then player falling to play advising. So we're going to have no exit time on both of these. And we need to add the condition checking for a velocity y. So off the top of my head, I'm not a 100 percent sure if positive y is going up or down on the screen. So we'll just try one way and then if that doesn't work, we just flip it. So let's see if the player is falling. Well, we would presume that that would be below 0 velocity, as in it's going downwards. So then let's put the opposite over here, plus sign velocity y and greater than 0 would be rising. I could very easily have that mixed up, but it's just a simple test. This should be all we need to test it for right now. So let's just keep this open here, down here, and then we'll see if we enter the player vising properly. Okay. So we should stay in player falling here and the velocity is definitely negative there. Okay, So I do have it right? So in this case, negative in Unity is going to be going down. So the player jump and player Double Jump are going to need behaviors. So I'm going to add a behavior over here that's called player jump behavior. And then I'm actually just going to add another player jump behavior for the top script as well. And for player double jump, you could provide a completely different behavior script. But I'm gonna see if we can just reuse player jump behavior and then change the values if we need to. So for you, just go ahead and create the player jump behavior and we'll get into the contents of the script and a second here. And for motion we're going to set player jump here. And then at the top we're going to have Player double jump. So the double jump motion we can see and the virtual guy, our assets, that's actually a separate jump for here. So that's why we're using a separate motion. So just one motion for this jump down here and then one motion for the double jump play different animation. So before we dive into the player jump behavior script here, and let's set up the graph for how we can transition into player jump. So for this character, how I'm going to set it up is that the player can only enter the normal jump if it is coming from an outside state like the ground. So I'm going to set up this character is that you can only do a normal jump if he is on the ground. So that means that the entry point for this player, It's actually going to be coming from outside of the aerial graph. And then after the jump animation is done playing, we're just going to transition back into play revising so that the animator can go between player rising and player falling as the velocity is above or below 0. So let's make the transition to play advising here. So this is going to be pretty simple. So for this transition, because our animation is a single frame, we might as well just transition to play revising immediately. So I'm going to uncheck the exit time, the transition there, and that should be all we need. Now if you have a jump that has multiple frames of animation, you might actually want to set it at x at time so that most or all of those Animation Frames of the Jump have already occurred before you go enter play a rising, but in this case, it's a single frame, so we're just moving straight into this state. Now we just need to set the outside conditions for how we can enter player jump. So I'm gonna go back to the base layer and then to ground. And from player one or player idle, we're going to set the option to jump. So I'm going to right-click here, make a transition. We're going to talk it up base layer and then States Air and then jump. And then the same thing with player idle, make a transition up layer states air jump. And the condition for this is going to be that the jump key has been pressed. So this is a trigger and we can do it whether the character is running or idling. So now if we go back to base layer, we can see that the transition already comes here from the ground back into player jump. And we can see that the condition here is jump. So I think we actually want to uncheck the exit time for both of these transitions so that the jumping can be immediate. So you can be running on one frame and then immediately jump into the air so you end up with an instant response time. So now we have the condition for how to enter play a jump and play a jump, or immediately go to Advising after it runs this little player jump behavior. Now let's go ahead and take a look at the player jump behavior. So I'm going to edit this script here, and we have a few variables in here. So jump impulse is going to be the force of the jump. So this bit here about the wall push impulse, we'll talk about that more in the next video about while jumping. So what we need to be concerned about here is on-state enter. We set the jump impulse variable impulse y and the animator. And that is going to be consumed in the movement script to the player input script in order to make the jump actually occur. And then this is also related to the wall jumping. So really, all we need for this video is the jump impulse and setting the animator value for the player input to consume. So back in player input, Let's see if we can find that jump bit. So in order for the character to jump, we need to check if the jump key is down. So in this case the name of the key is jump JMP. And you can set that up if you haven't already by going up to Edit and project settings. So we go down here to import Manager, and we can see that the jump key name is called jump as well. So that's where we get the variable name from. So we check if jump is down. If jump is down, then we set the trigger for the jump. So the jump trigger name is jump lowercase. And if it's not, then we reset the trigger. So we unset the jump trigger so that it can't be consumed as a jump. So a character will only jump on the frames where you are pressing the jump button down, so the jump trigger and therefore the jump will only occur on frames where you press the input button down. Now that also doesn't include holds, it's only on the frames where you press the button down, hence using input.txt button down. So it's just at that single frame instant. Then down here in the Physics script, we get the impulse y from the animator. So we set it in the jump behavior script and then report back in, in this fixed update. And then the impulse, why if there's any, it gets included in the impulse factor for moving the character after consuming the impulse. Why? We set the animator value for that back to 0. So it doesn't get consumed again until another script sets it up. And then right above that, we add the impulse factor to the character. So this is also going to include any impulses. But for right now we're just concerned about the jumping, why impulses. So that's basically all the script we need to have the jump, move the character. So let's go ahead and see if. So let's go ahead and test it out. So let's see if we can enter that jump state. So I'm going to play here, okay, make sure of course you have the jump trigger and the parameters. We hit space and then we get a jump. So right now, the jump impulse is really, really high. So we probably want to take that jump impulse and tone it down to something more like two. Let's go ahead and hit play again. Okay, and that's too little with the gravity. So let's go for something in the middle, like five. So I'm noticing that the player landing takes a long time to exit. Let's take the exit time here and set it to 0 so that it can exit landing immediately after it processes its state entered script and then also taking the player jump impulse and setting it to ten. Again, we want the jumps to be a little bit better. I'm also going to move the character back down here, since we've already tested the falling States, we just need to check that jumping now. So let's go ahead and hit space here. So, so far it's working for the most part, we just have a couple little issues defects. So one thing is that player jump to play advising as a transition. Doesn't have any condition or exit time, so that's not going to work. We either need to have a condition or an exit time. So I'm going to check x at time, and we can just set the exit time to 0 and the transition duration to 0, which should make it instantaneous and let it work without a condition. So let's go ahead and hit Play and let's see if we can have this transition back to play arising work again. So I'm going to space and enters player rising, and as soon as the velocity starts going negative, we start falling. So that's making the jump work well there, the player landing is still taking too long to transition out. So let's fix that as well. So maybe what we can set up for the condition here is to just check is on-ground still is set to true. And I'm going to uncheck Has Exit Time. I think that should work. So let's go ahead and hit Play. Can maybe we also need to take this transition and set the duration to 0. Let's see if that fixes it. Okay, yeah, actually, I think that's what we needed. Yes. Okay. Now it seems to be working correctly. So foil a lot of these transitions for this kind of sprite character, we want to make sure that those transitions are 0 so that it can move to the right state immediately. As a result of that, we don't actually need this condition here since it seems like this was the transition that was causing the issue. And let's just do Has Exit Time 0, 0. Okay, So now the movement is working much, much better for the character. This is how it should be. And now we just need one last thing which is to set up the double jump. So the double jump is basically going to be like the player jump, except we may want to change the jump impulse if we want the second jumped to be weaker. So we could say with this second jump impulse, we could say eight. And the main other difference aside from the value there, it's going to be how the sub-state machine enters the double jump. So when we want the double jump to be active is when the player is either rising or falling. So the character is already in the aerial states. We want to just check if the jump key is pressed and if the character has already doubled, jumped once or not. So the character should only be able to double jump once per aerial cycle. So in order to start jumping or double jumping again, they're going to need to land back on the ground. So that's where this parameter has doubled jumped occurred, is going to be checked or unchecked. So we need to make a transition from plagiarizing to play a double jump and play a falling to play a double jump as well. So the condition for both of these is going to be has doubled, jumped is set to false and is the jump button and is the jump trigger active? So let's set that for both of them and then jump as the trigger. And we want this to occur immediately. So uncheck has exit time, let's add the conditions for flowing back into rising and falling. So make transition to rising. So the player double jump animation actually has some frames we want to play. So this is going to be one of the cases where we don't actually want the exit time to be immediate, but rather once the player double jump animation has basically occurred. So let's set that same transition up for player double jump to play or falling. So transition duration set to 0 there. Or the conditions, if the velocity is above 0, then we'll enter play revising. So plagiarizing greater than 0 and then play with double jump to play a falling if it is less than 0. So for the double jump, we actually need to tell the animator that the double jump has occurred. So we'll do that by setting an animated property and we'll change the player jump behavior here, remove and we'll set up a different script player double jump behavior. So it's essentially going to be the same thing, except it has one extra line of code. So I'm going to change the jump impulse there to eight, just like we had before. Let's edit the script so we can see here in this player double jump behavior, we have the jump impulse and we set the jump impulse as a animated parameter, but we also set the boolean has double jump occurred to true. So when we enter the double jump, set that we have already doubled jumped. And by using that, we won't be able to double jump again until the character lands back on the ground and we reset that parameter. Now where are we going to set that parameter? Well, that's going to be in the player landing behavior. So the line we need here on state exit, when the landing is done, we set the parameter has double jumped and we set that to false. So this is a Boolean and we just need the parameter setup and the animator if we haven't already so has doubled, jumped, and that's going to be a Boolean parameter. So if you haven't added it in here yet, then go ahead and add it as a Boolean parameter and just make sure that the name matches up what you have in the scripts. So save all your scripts and let's go ahead and hit play and see if it works. So we hit play, let's watch the has doubled jumped Boolean and make sure it gets set properly. So I'm going to space and then space to double jump. Okay, the double jump does occur. And due to the landing script, when we land on the ground, it's going to be unset, which allows us to keep double jumping around the room. One other thing we can test, if I can get up here, is going to be if we fall off the edge, we should enter a double jump if we hit the jump button. So it shouldn't go into the normal jump, it should go into the double jump. So I'll just slide off the edge here and hit space for that double jump animation. And it works. We don't enter the normal jump, we enter the second chunk, but from the ground, reconnect space for a normal jump and then space again for our double jump. So that is working as intended. You may decide that you want to tweak the values a little bit if you feel like your character is jumping too high. So that's going to be really easy at this point. Just go in there, decreased the jump impulse a little bit and you'll be good to go. So in the next video we'll be adding a little bit more to this air sub-state machine by adding in wall jumping. 8. Wall Jumping State & Bug Fixing: So there's one animation state we need to add and that is going to be wall sliding. So I was thinking that we can add the wall slide state into the air state because we don't really want the character to transition into it when it's on the ground. We do want gravity to effect it, though. We may want to apply a gravity penalty so that it slides slower when it's on the wall. And then we can have the character be able to transition back into jumped from the wall so that it can still do its double jump. Before we create the state though, let's go ahead and create the animation for it. So I'm gonna open up project and then find the wall jump sprites inside of the imported pack. And let's split it up inside of the sprite editor. So let's go ahead and split it up either by South size of 16 by 16 or cell count. So count should be really easy here because it's obviously five. So let's go ahead and apply that. And now let's take this and put it in an animation. So I'm going to click on our character. I'm going to hit Control Six to open up the animation window. And we'll click on the drop-down, create new clip. And let's go ahead and store that into characters folder, since that's where I'm putting everything else. So player wall slide and then bring this brights n and then set the samples to 20. Okay, now we can click on our character and test the animation. Okay? So it does look a little bit silly when the character is not moving at all. But hopefully when we actually have some gravity applying, it'll look a little better when it's on the wall. So now let's go ahead and bring in the wall slide animation. So since we added the clip as a new clip on the character, a new state has been created with the motion added on. We're going to copy this into air. So Control-C, Control-V, and we'll move it right about here. I'll move lending out of the way. But we're going to want any state to be able to transition to this wall slide. Before we do that though, let's delete the copy from the outer base layer. Go back in here, organize things a little bit. And now we want to set up the conditions for any state transitioning to wall slide. So any state can go to Wall slide if the characters on the wall. So we're going to need another boolean variable for that. So like is on ground we want, is on wall. For organization purposes. I'll move it up there closer to that first Boolean. Okay, and then we'll add that as a condition here. So is on wall is equal to true. Now once the characters on the wall, there's three possibilities that'll happen. One is slides all the way down until it lands on the ground. But that's already start off here with any state to landing with the landed on ground condition. The other is that the character slides down until there's no more wall for it to grab onto, but it doesn't reach the ground. In which case we should have a transition to play your fall. So I'm going to set up this transition here, make transition to play or fall. And the condition is going to be, is set to false. Wong going to want to exit time for that and no transition duration as well. For the And I think for the initial transition to the wall, we are not going to want any transition duration as well. So I'm setting that to 0. The third possibility is that the player presses jump while it's on the wall. So we're going to make a transition here and the condition is going to be jump. So basically if the jump trigger is active, then we want to transition into a jump state. The third possibility is that the jump button is going to be pressed. So we can transition into player jump here when jump is pressed. So let's go ahead and set that jump condition here. So if jump is triggered them we're gonna transition. We don't need any exit time or duration as well. So this is going to be a few things we need to set up about this jump. So one thing is that we're going to need to make sure that the character actually jumps away from the wall, not just straight up. So that is wall is going to be set to false. And the way we can do that is by having an x impulse added with the jump as well. So the first thing that we're going to need to set up for this to work is to set the condition for when is on wall is going to be true or false. And we'll do that back in the player and port script. So it's going to be very similar to when we checked is on ground. First, we're gonna need to get the direction that the character is facing. And then we're going to need to cast from the collider and see if it connects with anything that would be considered on the ground layer. So I went ahead and wrote the script here and advance. And let's go ahead and walk through with it and then make some changes on the animator so that all of this works correctly. Okay, so first off, we're going to check if the character is on the wall and we'll get to that in a second. And then if it is on the wall, and then we set that boolean into the animator, just like we did for is on-ground. So that is going to be a Boolean stored on the animator that we can use in other scripts or transitions. And so then we just need to come down here to check if on wall, you'll notice that it's very, very similar to the check if on ground script. The main difference is we take a look at the local scale of the transform to determine which direction the character is facing. So you might be called on the base layer of our animator, we had a script setup called player flip. And that player flip was setting the local scale of the characters transform to either be positive one on the x or negative one to flip the direction to face the left. So taking those same values, we can use that here. The local scale and the x value of the local scales either going to be positive or negative. So taking the sign of that, which is going to either return one if it's 0 or greater or negative one if it's below 0, we can multiply that by vector two dot right, to re-cast in the right direction. So if it's facing right up here, this is going to return a value of 11 times a vector is just going to be that vector and the vector is right direction. Otherwise, if we get negative one here, then negative one times the right vector is gonna give us the left vector. So aside from that, it's the same stuff. Ground check filter. We have wall hits as a list re-cast 2D setup at the top. And just to store the list of hits that we find whenever we do a ray cast. And then we also have a variable for the webcast distance. Now I keep saying re-cast. So, so here I'm making the call that it's probably better to do a ray cast rather than casting the entire collider. So if you do a collider cast, what it's gonna do is it's going to take the shape of the collider, in this case, like an oval shape. And it's going to bring a copy of that downwards and the amount of distance for the ground check distance. But if we do a full collider cast on the rigid body main collider. What it's going to do going left and right is. Come in contact with something that would be the ground and call it a wall. In many cases where we wouldn't really consider the character to be on the wall at all. For instance, if there is a minor slope going up, like a ten degree angle, this would collide with that if it was being cast in the left direction. So what we can do instead is take a re-cast from the middle of the character, from the middle of the collider, rather cast that into left and right direction. And then that's going to mean that basically the character, the character is height, is split in half. And the webcast, I think, comes from about right here and goes out to the left. So much more accurate to where the hands could be in terms of grabbing the wall. It makes sense if the webcasters coming from down here where it was barely touching the wall, only the foot would be touching the wall. And the character really doesn't have anything to grab onto. So it doesn't really make sense for it to be in a wall slide. So that's why we're doing a re-cast here rather than a full cast of the entire collider. So the difference here is instead of using dot cast, dot re-cast to put all of the parameters are otherwise the same. So once we get the wall hits back, we just check if it's greater than 0. And if so, then yes, it's on the wall. Otherwise it's not. So pretty simple. But there is one problem here, which is that any state actually allows you to pull in from states. That would be the problem with doing a any state transition to wall slide here is that any state means any state in the entire state machine, including base layers or states coming from ground. So when the character is on the ground, but also on the wall, it can go to the wall slide even with the webcast. So let's hit play and see what happens here. So hitting the ground, It looked fine there. And I think the reason for that is because of this switch to the re-cast. You can still get those cases where if there's a slope that re-cast may be considering it to be the wall, so you have to be careful there. So we have their webcast check of 0.06. Let's go over to the wall. And okay, maybe the re-cast distance isn't long enough. So the request is coming from the center of the collider. That's why the distance needs to be longer. But we get to the wall there with a 0.7. re-cast wall distance. And maybe we need to change the shape of the collider so that the character is closer to actually sticking on the wall. So the problem here is that the character can just walk up to the wall and start grabbing it, which isn't really standard behavior for platformers. But we can fix that still. We just need to add another condition for the any state transition. So we'll just add here is on ground, is set to false. Let's go back in here and set the re-cast wall distance. So 0.7. and apply that to the prefab. What we can also do is go into the Prefab here and change the shape of this overall. So as things are right now, the character sands and upper bout here, but the collider shape is bigger than that. So we actually probably wanna bring in this collider shape n, so that it looks more accurate to our art. Edit the capsule collider, bring in our values a little bit. And then let's go ahead and hit play and test. So when we get to the wall, it's not actually finding it. So maybe, maybe, maybe shrinking the webcast didn't mean that we need to increase the value here, okay, So with the 0.8. We can't get to the wall. But now that the characters on the ground and on the wall, it doesn't actually go to this state, which is more like what we would want. So let's try to jump onto the wall. Okay, so we get to the wall. So we get to the wall here, the character kinda slides down it due to the gravity, though probably faster than we'd want on the wall. One problem is that the character kind of bounces off. So what we'll need to do is actually stop the characters velocity when it gets to the wall. Okay, so what we're going to need to do here on state enter is a to a set of Boolean value which the player input can take a look at. So we'll call it animator dot set Boolean. So with this, the player input can see that stopped velocity is set to true and then stop velocity on the rigid body. So let's go ahead and take a look at that. So we'll check is stopped velocity whenever fixed update is run. And we'll do animator dot, get bool, PAP, dot-dot-dot velocity. Okay? So if is stop velocity, then we wanna take the rigid body and we'll set the velocity to 0 or the vector 20 rather. And I think that's about all we're going to need for that. Just make sure that the variable for the string is added to the strings lists and that they stopped velocity parameter is added to the animator. Okay, let's go ahead and test it if the velocity to stop when the character gets onto the wall. Okay, it does nice. And you can see that the gravity all body effects the character a lot less because we have the friction coming from the wall. So as long as the character is actually hugging the wall, it's going to slide down very, very slowly. Okay, so let's go ahead and test it and jump onto the wall so that velocity does stop. And we do have a problem though, which is that it's stopping every single frame. So it stopped velocity here is still set to true. So we need to actually consume that Boolean. And in a sense, I wouldn't use triggers, but for some reason there's no way to get if a trigger is set or not outside of the animator. So let's, let's go to player input. And then when this is here, and we also do wanna do animator dot set, Bool, POP stopped velocity. So in a sense, we created a trigger using booleans, which should work. Okay? Okay, so let's see what happens now when we actually get onto the wall for the first time. And we'll see how the gravity effects it. Ok, so the characters sliding down now, Oh, it still, It's still actually is set to true. Weird. Okay, so here's actually the problem in the code. Right now. Any state can go to all slide, but we don't want Wall slide to be able to go into all slide using this transition. So there's actually a setting here. And luckily that we can check off in order to make sure that if it's in the wall slide state, it's not going to go back to the wall slide state over and over again, which would be setting stopped velocity to true basically on every frame. So if we uncheck this, then once it's in wall slide, it can't make this transition anymore. So it should only enter while slide once until it actually, until the wall slide actually leaves the state goes to something else and then the character gets back to the wall, says things work right now. Pretty much it's working well. The wall sliding goes to the bottom. If you'd like go though, it is possible for the character to fall off the wall. That's the nature of the dynamic rigid body. So the last thing we need to do is to make it so that when we're jumping from the player while slide state that it actually launches off the wall. And I think what we can do for that is rather than putting script inside the wall slide will just check if we're on the wall when we actually do the jump. For player dot jump, rather we can check it on the wall and also not on the ground because it would be a little weird if it launched over here from the ground. But let's go ahead and set that up inside of the jump script. So in player jump behavior, we're just going to check what kind of state the animators. And so animator app.get Boolean. Pap dot is on wall. And we want to make sure that's set to true. And we'll also want to check get boolean. Pap is on ground. And we want that to be set to false. So if both of those conditions are true, then we're also going to set a impulse x for the player input to consume. So we can call this wall Porsche impulse, and let's give it a float value. We can just start with 20th for now, let's go ahead and add in a string for the impulse. And then the player script will get the impulse X as well. Okay, and we can put a or here. If impulse x does not equal 0, then we'll try to consume that as well. Add force, new vector two. Oh, okay, actually, rather we don't need that and we can just put that into here. So we only need to add the force once. And so animator at outset float well, we wanna do that for the X value as well, since we're consuming both of them at this moment in time. So impulse x, and we'll set that equal to 0. And that is pretty much all we're going to need there, I think. So let's go ahead and test it out with this wall Porsche impulse. So we hit play, we get onto the wall, hit Spacebar. Well, what happened is that the parameter doesn't exist. So let's actually add that parameter, add a float variable and pulse x and move it up here. Okay, let's try one more time. Okay, so let's go ahead and hit play, test it one more time. Jump at the wall, hit space and the character goes flying off to the side, which is close to what we want, but that's probably a little extreme. Let's drop that wall impulse to something more like five. And let's try again. Okay, so character jumps at the wall. We hit space to jump and it comes off the wall. So what happens if we're holding left really closely to the wall? We can still get that jump impulse. So this seems to be pretty close to what we want. We have r double jumping. We can get to the wall, jump off the wall, do another double jump off the wall. So from this point, all of the functionality is pretty much working. We just need to perhaps customize the numbers a little bit so that our character moves in the patterns that we want. Having the right amount of impulse on each jump, the right speed, the right amount of friction. And also whether we want any linear drag on our character or not. Okay, so one thing I do notice is that sometimes there are these cases where the character lands on the ground, but it doesn't necessarily actually transition to the landing state quite right. So I think what might be the issue there is that the trigger is being reset here as I'm going to try and taking this away from the player input script. And then we're only going to consume that landed on ground inside of the player landing behavior. So let's go ahead and open that up. And then when we get to on enter here, will do animator dots, reset trigger, PAP dot, landed on ground. Okay, so now let's go ahead and clear the console and test all of that. So I'm not saying the issue anymore. So hopefully that does fix that. So here's another minor bug that needs fixing. The wall jumping works fine when we do it from a left wall, but when we go to the right wall, you can see that it doesn't work because the force is being applied in the right direction still. So what we need to do is applied the force in the right direction. So what we can do here is that we can get the local scale of the transform and then check the direction of the x by using math sine. So let's go ahead and get the float, and we'll call it x direction sine equals transformed local scale dot x. And we'll get the Math.min of that. So Math.min, math F dot sine rather. Put all that in and we'll multiply that by the impulse here. Okay, so this should work just fine for the wall jumps. If you have any more impulses that would come from your scripts, then you might want to change this a little bit, but I think this should work fine for now. So let's go ahead and get ender. Okay, so let's jump onto the wall, hit space for him. Okay, the only problem is that this impulse is positive, so it's actually giving it in the wrong direction, in the reverse direction. So back in the player jump behavior, we can just take this wall Porsche impulse and make it negative. By default. Maybe I'll put in the tooltip. Generally should be negative so that it pushes in the reverse direction. Okay, now let's go back to our player prefab and just make sure that the wall impulse is negative. So I ok, right. It's actually on the animator. So player jump and we'll do negative five for the wall Porsche impulse. And we can see the little tooltip there. So let's hit play and test it out. Okay, so we jumped on this wall space to jump off. And we can get to this wall base to jump off. So let's try wall jumping up here. Okay, so now let's test if we can actually do the wall jumping. One more thing I will add is I'm just going to reset that trigger has double jump to inside of wall slide as well. Because if we enter the wall slide than we do, want to allow the character to do a double jump again. So let's reset that trigger PAP. Dot has doubled jumped, and that should be everything we need there. So let's go ahead and hit play and we can test it out again. Okay, so first jump, and we get a double jump in. Our character can double jump, jumped up bottom. And we can get pretty much all the way up there. So that's pretty cool. Yeah. So I think that just about fixes the bugs so far. I one final thing I would recommend is that you toned down the wall re-cast distance of your character. So I have it at 0.5. five-year, and that allows me to get it very crisp with the actual pixels of the character. Another thing you can look at doing is making sure that your capsule collider is set to values which are understandable. So here I have 01 for the offset and size of x, and then offset y as 0.251.5 for the y size. What's important is to make sure that the bottom pixel a lines up nicely with the bottom of your capsule collider or any other collider that you decide to use for your body. So that's pretty much going to wrap it up for the fixes I think need to be made. Once again, if you want, you can customize things such as the rainforest. Once again, if you want, you can customize things such as the running speed of your character. You can change the friction on the physics materials for both the ground in the air. And if you want, you can try playing around with linear drag and seeing if that gives you a movement that's close to what you're looking for. So that's pretty much going to be it about setting up a platform or character inside of Unity. So thanks for watching this series to the end, I friend Chris and hopefully I'll see you guys in some of my future content. 9. Adding a Background and More Ground for Character: So just a little bit of bonus content here. I'm going to build out a few more spaces for our 2D character to move around on using the pack, the pixel adventure pack. If we look in the background folder, we can see that they actually added in some backgrounds that we can use for our games as well. So to add this, I'm going to use a 2D sprite. And let's go ahead and try this brown one out here. So what we're going to need to do is to tie all this sprite. And it needs to be set to fall back to modes. When you click on your sprite, that's meant to be a background. You wanna go to the Mesh type and change that to fall racked. Also going to go ahead and change the pixels per unit to 16 here, since that's what we were setting for the course. So let's just make everything consistent. Now, we should be able to tile this background just by stretching it. So let's go ahead and try that out here to make it the background. We can put it's order n layer as negative one. Or we can put it on a new sorting layer that sits behind everything else. Maybe we'll do that. So let's go ahead and create a sorting layer here. So I'll call this background. And background always going to be behind the default layer and everything else. So for our new sprite is going to be named that back ground. Going to position this at the top. And we can actually just set the sorting layer 0 again. As long as it is sorting layer background, it's going to still be behind everything on the default layer. So let's go ahead and drag this out here. If we look in game mode, we have the background feeling pretty much everything. So now let's just go ahead and add some extra tiles. So we have the ground, the tile palette, and we do have some extra stuff we can go ahead and play with here. So I'm just going to be placing some extra stuff into the scene and our character will be able to interact with it. So let's just create a test box with ceilings, and perhaps that's good enough for now. So let's increase the height of our background. Let's just make it much, much better than we need it to be so that the background is always showing. And then we can go ahead and hit play. And our character is going to be able to move around here. 10. Cinemachine - Easy & Smooth Follow Camera for Your Player: Now, when we hit play in this game world, you can see that the camera doesn't follow the player at all. This is actually pretty easy to fix inside of Unity because there is something called a cinema state machine. So if we go to Window and then Package Manager, we can take this drop-down from in project to unity registry and put in cinema or just Senna. And you should be able to find the cinema state machine. So at this into my machine does, is sets up a bunch of camera tools that you can use to make the movement of the camera smooth and easily controlled with minimum coding, if any, on your part. So for instance, one thing we can get a smooth follow camera. So once this is installed here, then we'll get this cinema machine menu. And what we're going to want is a virtual camera. So I'm going to create a virtual camera there. If you click back on your main camera, you'll notice that a cinnamon machine brain has been created. So the new cinema machine gameObject is basically going to control that camera in a sense. And what we wanna do is follow the player. So I'm going to follow, select the transform of the player. And now when we hit play, we should get some follow camera movement going on. Okay, so yeah, just like that, we have a working follow camera. How cool is that actually?