Wall Grab/Climb/Slide - 2D Platformer Player Controller - Part 23

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is up guys welcome to barton my name is heinrich and today we're going to take a look at three different states we'll look at our wall slide state our wall grab state and finally our wall climb state this is going to get us ready to move on to our wall jump state in the next part so before we jump into unity let's just talk a little bit about the logic and see what's going on so of course we're going to have our wall slide state our wall grab state and our wall climb state all of these are children of our touching wall state so for our wall slide state we're going to transition to this if we're not grounded and we're giving x input towards a wall that we're touching this will cause us to go into the wall slide animation and just slow our y velocity down so seeing as one of the requirements for wall slide is that we're not grounded that means we can only transition to this state from our in air state after that we have our wall grab state which is just a state where we stop the velocity of the player on a certain point on the wall and so we can transition to this from our in-air state or from our ground estate if we're standing next to a wall so if we give grab input we'll grab onto the wall after our wool grab state we have our wall climb state and this is just if we're grabbing the wall and we give a positive y input we'll climb the wall as you can see if we're grabbing the wall and we give negative y input we also go to our wall slide state so that's what we're going to be working on today let's go ahead and jump into unity okay so to get started let's head to our scripts folder player folder player states folder and then let's go ahead and go to our super states and create our touching wall state so right click create new c-sharp script and we'll just call it player touching wall state we can then go ahead and open that up and before we do anything here let's go ahead and create our other three states so let's come to our sub states folder let's create a new c sharp script the first one is our player wall slide state next we have our player wall grab state player wall grab state and then finally we have our player wall climb state like that we can go ahead and open up all three of these as well so player wall climb player wall grab and player wall slide perfect okay so let's just get the basic state stuff that we have to set up out of the way so we can go ahead and delete all of our pre-generated code and our player wall slide state is a child state of touching wall so let's actually first go and set up our touching wall state get rid of this and then we'll just make it inherit from player state and then we generate the constructor so quick actions and refactoring generate constructor let's save that and then go back to our player wall slide state so we'll make this inherit from player touching wall state and then go ahead and generate the constructor save that next is our player wall grab state so we can delete this then make it inherit from player touching wall state and generate the constructor and then finally we have our player wall climb state so again delete this code and then make it inherit from player touching wall state and generate the constructor perfect so now all of these are ready to be states the next thing we can do is set up the objects in our player class so let's go ahead and open that up so that's under our player finite state machine folder player so let's go ahead and open up the state variables region and we have three new states so the first one is going to be public player wall side state and we'll just call it all slide state and then of course we give it a public getter and a private setter then next we have our player wall grab state so public player wall grab and we'll just call it wall grab state then give it a public getter and a private setter and then finally we have our player wall climb state so public clear wall climb state and we just call it wall climb state now we can go ahead and create the objects in our awake function so let's minimize our state variables and open up our unity callback functions so the first one is our wall slide state equals a new player wall slide state and we'll pass this as the player state machine as the state machine player data as the player data and then finally our animation boolean name is going to be wall slide lowercase w and then next we have our wall grab state so we'll set this equal to a new player wall grab state with this as the player state machine as the state machine player data as the player data and then finally our animation boolean name is just going to be wall grab again with a lowercase w uppercase g finally we have our wall climb state so wall climb state equals a new player wall climb state with this as our player state machine as our state machine player data as our player data and then finally our animation boolean name is just going to be a wall climb just like that and now we have all of our states set up okay so the first state we're going to work on is our wall slide state now to know if we should be wall sliding or not we need to know if we are detecting a wall so let's go ahead and set up our wall check if we go ahead and go back to unity and take a look at our old player you can see we have this wall check child game object that is just at the position zero zero zero so let's go ahead and click on our player and create a new empty game object let's just call it wall check and we can just leave the transform as is it's in the right place so that's like in the middle of our player over here next we need to go ahead and set up our wall check distance in our player data script so let's go ahead and open that up and then underneath our check variables let's just create another public float and we'll just call it wall check distance and by default let's set it equal to 0.5 just like that now we can come back to our player script and under our check transforms let's open that up and create another serialized field private transform and we'll just call it wall check we can go ahead and close down our check transforms and our unity callback functions and so now we need to create a function that we can call to check if there is a wall or not so let's open up our check functions and underneath check if grounded let's create another public pool and let's just call it check if touching wall like that and then all we have to do in this function is return physics 2d dot raycast and for this raycast our origin is wall check dot position our direction is going to be vector 2 dot right multiplied with our facing direction and then next our distance is going to be player data dot wall check distance and then finally our layer mask is player data dot what is ground and now we have a function that tells us if we're touching a wall or not perfect okay so now let's set up our transition from our in air state to our wall slide state so you can see the condition is is touching wall and our x input is at the wall and our y velocity is less than zero so let's go ahead and open up our player in air state so player states sub states player in air state and so the first thing we need to do is create another private bool that is going to be is touching wall and then we can come to our do checks and add that in there so is touching wall equals player dot check if touching wall like that now we just need to come to our logic update function and we'll create another else if so else if and the conditions inside of this else if is going to be is touching wall and x input equals equals player dot facing direction so our wall check is returning true and the x input that we're giving is in the direction of the wall so if this is the case then we're going to just transition to our wall slide state so we'll say state machine dot change state to player dot wall slide state just like that so now once we're in our wall slide state all we need to do is limit our y velocity so before we can do anything here let's go ahead and come back to our player data and let's create a new header for our wall slide state so header wall slide state and then underneath this header we'll just say public float wall slide velocity and by default let's just set that equal to three now we can come to our player wall slide state and let's generate our overrides so in this case we really only want our logic update function so we can just go ahead and deselect all select logic update click ok and then in here all we need to do is say player dot set velocity y and the velocity you want to set it to is going to be player data dot wall slide velocity and it should actually be negative this seeing as we're going down so we can just put a negative at the front now the only thing we have left to do inside of the state is check for our grab input but we'll get to that in a little bit so for now we need to work on our transitions out of our wall slide state so you can see we have this transition going from our touching wall state to our idle state and this happens if we detect ground or we don't have a grab input otherwise we also have this transition going to our in-air state and that happens if we're not touching a wall or we're no longer giving x input or not giving grab input and we're not detecting ground so our transition from wall slide state back to our in air state comes from our touching wall state so that's what we're going to work on next so let's go ahead and go there so let's first go ahead and generate all of our overrides generate overrides and we just don't want the first three so again really we don't need all of these but for our bigger states i like just having all them in there just so they don't have to come back later and generate them again so the first thing we need to do is do our checks so we want to know if we're touching a wall we want to know if we are grounded or not and we also want to know what our x input is so let's go ahead and declare variables for all three of those so first we have a protected bool and we'll just call it is grounded next we have our is touching wall so protected tool is touching wall and then next we just need to read in our x input so protected int and just call it x input and now we can go ahead and add this to our two checks so the first one is is grounded equals player dot check if grounded and then is touching wall equals player dot check if touching wall and then x input we put in our logic update function so x input equals player dot input handler dot normalized input x okay so let's first work on our transitions to our idle state so we can go ahead and say if is grounded and then we also have to add our grab input here but we don't have that yet so we'll just open up our if statement and then in here we just say state machine dot change state to player dot idle state then next we have our transition to our in air state which again is we're not touching wall we don't have x input and actually this x input over here is wrong it should be we either don't have x input or the x input is away from the wall and then finally we're not grounded which in this case we don't really have to add they're seeing as we already have is grounded over here so we can just say else if not is touching wall or x input does not equal player dot facing direction so in this case if x input is 0 or negative 1 if the wall is on our right we will trigger this transition so in here we just say state machine dot change state to player dot in air state and so we're actually ready to test out our wall slide so let's go ahead and go back to unity and then we just need to create our wall slide animation so let's open up our animation window and then come to our sprites folder player and open up our character so our wall slide animation is currently set up for sprites 17 to 21 but these are all just the same sprite i just put them all there because i'm still planning on adding some more animations to that later so we can just use the first sprite so let's go ahead and click on our player and then create a new animation navigate to our animations folder player and then we'll just call it wall slide we can then go ahead and drag in our sprite and seeing as we only have one we can just leave the sample rate at 60 and that's good so we can go ahead and close down our animation window and then let's come up to our animator and the first thing we need to do is create our new boolean parameter that is just called wall slide and for lowercase w go ahead and drag that to the top and then let's position our wall slide animation and then make a transition from entry to wall slide click on it and the condition this time is wall slide is true then we can make a transition from wall slide to exit click on that untick has exit time underneath settings we can change our transition duration to zero and then add the conditions that wall slide must be false so just in case you're wondering why keep dragging the new parameters up to the top it's just so that it's the default parameter that gets added when i create a new condition just saves an extra step perfect so let's give this a try let's just quickly click on our player i think we need to add our wall check transform let's not forget that and yeah let's see if it works so if we run up to a wall yes you can see we transitioned to a wall slide except if we tried jumping we immediately transitioned to a wall slide okay so let's go back to our scripts and let's come to our player in air state so currently we're transitioning to our wall slide state if we're touching a wall and our x input is towards the wall but we also need to make sure that our y velocity is less than or equal to zero such as go ahead and add another and and we'll just say player dot current velocity dot y is less than or equal to zero let's go ahead and try it out now perfect as you can see if we're falling down we start sliding and we can also play around with our wall slide velocity it feels like it's a little bit too fast for me so let's set that to two instead that's better okay and of course now you can add like little particle effects whatever you want we actually also need to test out our transition back to idle yep so as you can see when we touch the ground we transition to idle but because we're giving a x input we transition to our move state perfect so everything works so now we're going to go ahead and work on our wall grab state so the first thing we need to do is add a new input so let's come back to our player folder input folder and then open up our player actions asset i'm just going to go ahead and dock that up here again okay so currently we have our movement and our jump actions so let's create a new action and this one we'll just call grab in this case our action type is going to stay button and let's click on the first binding and then let's set that to control on keyboard and don't forget to tick keyboard as our control scheme and let's go ahead and add a new binding and then click on path listen and for controller i'm going to use write trigger so again we have the two options we're going to choose the gamepad option and then make sure we tick gamepad and now we have our new grab input set up so now we just need to create a function for it in our input handler so we don't currently have that open let's open that up and let's scroll down underneath our on jump input let's create a new function it's going to be public void and we'll just call it on grab input and then of course our input parameter is going to be input action dot callback context and we'll just call it context and this function is going to be very simple all we're going to do is on context started we set our grab input to true and on cancelled we set it to false so let's actually go up to our variables and create that boolean so we need a public bool call it grab input and then of course give it a getter and a private setter and then in our on grab input function we'll just say if context dot started then we set grab input equals true and then if context dot cancelled we just set grab input to false so of course once we start holding the button it gets set to true and when we let go it gets set to false so that's it for the input handler for now now we need to come back to unity and then click on our player and then come to our player input component and then open up our events gameplay and now we have this new grab callback so let's go ahead and add to our list and the object is going to be our player input handler and the function we're going to call is under player input handler and it's the on grab input okay so that's everything set up for this so now let's set up the transitions to our wall grab state so we have two transitions in there one is from our grounded state so in this case if we are touching a wall and we do give a grab input we transition to our wall grab state and the other one is from our in air state which is basically the same condition so if is touching wall and grab input okay so let's start with our grounded state do we have that open we do not so let's go ahead and open up our player grounded state and the first thing we need to do is add our is touching wall so we have a private pool is touching wall and then we just have to go ahead and add that to our checks so is touching wall equals player dot check if touching wall we then also need to read in our grab input so let's create another private boolean call it grab input and then we'll come to our logic update function so after we read in our x input and our jump input we'll say grab input equals player dot input handler dot grab input then we can come and create another else if and the conditions for this else if is is touching wall and grab input then inside the function all we say is state machine dot change state to player dot or grab state then let's come to our player in air state so we already have our is touching wall boolean now we just need to read our grab input so private bool call it grab input and i just realized in my player grounded state i spelt grab input of a capital g so let's just go ahead and fix that lowercase g perfect okay back in our player in air state let's go ahead and read in the input in our logic update so after we read in this input we'll just say grab input equals player dot input handler dot grab input then after this we can create another else if but now let's think about it we want to transition to our wall grab state to be more important than our wall slide state so we'll put this else if in front of this wall slide transition so that way we'll transition to our wall grab state if we happen to be holding down the grab button and input towards the wall at the same time so let's open up this else if and the condition is his touching wall and grab input like that then inside this else if we just say state machine dot change state to player dot wall grab state so let's go ahead and take a look at the state machine diagram so we have these two transitions transition setups and now we can work on our wall grab state so in this case it looks like we're going to read in our y input and then based on that we'll either transition to our wall climb state or we'll transition to our wall slide state so let's go ahead and take a look at that let's come to our player wall grab state and then let's generate our overrides just like that and so actually as you can see we need to read in our y input in our wall grab state and our wall climb state because based on that we transition between the two so we might as well just write the code to read in the y input in our touching wall state so let's actually go ahead and do that first let's come to player touching wall state let's declare another protected int call it y input and then just add that to our logic update function so after we read an x input we'll say y input equals player dot input handler dot normalized input y now back in our player wall grab state this data is actually super simple as well we can come to our logic update function and then all we need to do here is we'll say player dot set velocity x to zero and then player dot set velocity y to zero so we're effectively freezing the character in place next we just need to set up our transitions so we'll say if y input is greater than zero so we're pushing w or holding up on the left stick then state machine dot change state player dot wall climb state so if we're grabbing the wall and we give a positive y input we'll start climbing the wall and then now if we give a negative y input we should wall slide so we'll say else if y input is less than zero and so we're saying less than zero and not less than or equal to zero because if we're not giving any y input we just wanna stay in our grab state so after this we'll say or not grab input but i just realized we're not actually reading in our grab input so let's just go to our player touching wall state and let's add that as well so protected bool and again just call it grab input and let's just move that up to the other bools and so in case you didn't know this if you hold alt and then use the up or down arrow keys you can move lines around okay let's go to our logic update function and after read in our x and y input we'll say grab input equals player dot input handler dot grab input so that should fix it in our player wall grab state yes so else if and then in this case we just say state machine dot change state to player dot wall slide state perfect so all of that is almost working the last thing we need to work on is our player wall climb state and this state is also really simple in our player wall grab state we actually only need to generate our logic update function we don't really need the rest of these but we'll just leave it there for now so in our player wall climb state we can generate overrides and in this case we also only need our logic update function so let's generate that and then all we need to do in here is set our y velocity to a wall climb velocity so let's come to player data and let's create another header and the title for this header is going to be wall climb state and then we just declare a public float and we'll just call it wall climb velocity and by default let's set this to 3 as well and then we can come back to our player wall climb state and then in our logic update function we just say player dot set velocity y to player data dot wall climb velocity and then next we just need to set up the transition back to our wall grab state so we'll say if y input does not equal one so it's either going to be zero or negative one then in this case state machine dot change state two player dot wall grab state and that should be all of that set up so let's go back to unity and set up our animations so we can bring up our animation window click on our player and let's create a new animation clip we just have to navigate back to our animations folder player okay so our first animation is going to be our wall grab animation so we'll just call it wall grab and then our next animation is going to be our wall climb animation then we can go to our sprites folder player folder and the sprites we use for our wall climb is it looks like it's a sprite 55 to sprite 66 so let's start with the wall climb animation let's just drag that in there if we play it of course the sample rate of 60 is too much so let's change that to 15. that works it might be a bit fast let's try 10. i did not click enter that looks a bit better nobody climbs a wall that fast cool so that's our wall climb animation now for our wall grab animation we'll just use the first sprite from our wall climb animation so that is sprite 55 we can just go ahead and drag that in there and of course he's just going to hold this position so in this case it's just one frame so the sample rate does not matter next we can go ahead and go to our animator and set up our animation transitions we can also close out of our animation window and here we have our wall grab and our wall climb animations so now we need to go ahead and create our two new boolean parameters the first one is going to be our wall grab and let's just move that up and set up the transitions so from entry we'd make a transition to wall grab click on that add a new condition and the condition is wall grab is true then make a transition from wall grab to exit click on that make sure we untick has exit time set the transition duration to zero and for conditions wall grab is false our next parameter is our wall climb so another boolean called wall climb go ahead and drag that up to the top make a transition from entry to wall climb click on that add a new condition wall climb is true then make a transition from wall climb to exit click on that untick has exit time and set the transition duration to zero so i think we're ready to run this now let's see what happens so if we run against a wall and we hold ctrl we're transitioning quickly between our grab and grounded state so that is because we forgot a condition in our player touching wall state so actually if we just take a look at our state machine diagram you can see that to go to our idle state it's ground detected and not grab input but we didn't have our grab input yet when we set this up so currently it's only is grounded so just go ahead and add not grab input like that okay so let's go ahead and try it again if we run up against the wall it looks like there's a lot of stuff that i forgot but it only seems to happen when we're climbing oh what is happening [Music] what did i miss okay so it looks like i didn't add a condition to the transition from wall climb to exit so don't forget to do that add a condition wall climb must be false okay perfect we also need to add the grab input to our transition to our in air state so currently we're saying if not is touching wall or our x input does not equal player facing direction so over here we want to add a bracket in front of our x input part and one after that and then inside the bracket we'll say and not grab input so we'll only transition to our in air state if we're either not touching a wall and both of these are true so we're either giving x input away from the wall and we're not holding the grab input so let's go ahead and try this now fingers crossed i didn't forget anything else don't forget to save and then let's try this again okay perfect so if we run up to a wall and we hold ctrl you can see we go into the grab state if we hold w we start climbing the wall if we let go of w we start sliding down why are we sliding down but if we hold s we go into the actual slide state so why are we not holding position in our grab state okay so i actually forgot something really important in our player wall grab state so setting our x and y velocity to zero is not enough because we set the velocity to zero and then our physics update happens and gravity starts adding a negative y velocity so that's why we keep sliding down a little bit so what we also need to do is track what the position is when we enter the state and then just keep resetting our player position to that the reason we set the x and y velocity to zero zero is to keep the camera centered on our player so let's actually quickly do that so instead of setting our x and y velocity to zero let's create a new function and we'll just call it private hold position and that should be private void hold position and then i just move this set velocity functions in there and now let's go back up to the top and let's declare a new variable that is going to be a private vector2 and we'll just call it hold position then in our enter function we'll say hold position equals player dot transform dot position so the moment we enter the state we say okay what is our current position and this is now going to be the position where we hold the player then let's come to our hold position function and before we set the velocity let's just say player dot transform dot position equals hold position perfect now we just need to call hold position from our logic update function and then we also need to call it in our enter function like that don't forget your semicolons okay so let's try it out again so now when we climb up you can see if we let go of w our character stays where he is and he doesn't slide down let me show you what happens if we remove this player that set velocity x y well x doesn't matter but let's just comment out the y one so let's save that and let's try it out again as you can see our camera starts drifting down that's because our cinemachine camera works with the velocity of the game object that he follows so i don't quite understand exactly what's happening but that's what i can imagine is happening so by setting our y velocity to zero let's actually open up our camera so you can see this yellow dot you can see the yellow dots moving down and the camera is busy tracking that dot but if we set our y velocity to zero and we jump up against the wall you can see the yellow dot stays where it is and our camera tracks our player perfectly cool so now we can walk up the wall let's try that with controller so we don't get that annoying error so if we hold right trigger and up on the left stick we climb if we hold down we start sliding okay we don't have a transition going from our sliding animation back to our wall grab animation or state sorry so let's go ahead and take a look at that so in our player wall slide state yeah we forgot to set up this transition this is where to do's come in handy guys so all we have to do here is say if grab input and our y input is equal to zero then we transition to our wall grab state so state machine dot change state to player dot wall grab state so let's try that out again if we hold up we climb if we hold down we slide and if we let go of down we stop perfect of course if we let go of the grab button we drop and if we give a x input towards the wall we slide that's awesome okay so currently we wall slide if we give a x input from our grab state oh i know why that is so if we do this with keyboard and mouse so if we walk up a little bit and we're in our grab input and we hold d we don't start sliding but if we push right on the controller we do start sliding let's try that again while we either start sliding or we start climbing and that is because of our normalized x and y input if we go ahead and take a look at our player input handler so input player input handler and we come to our on move input you can see that the smallest x or y value is going to be turned into a one unless it's completely zero so i think we need to add a little bit of a tolerance here so we'll keep this here but instead of always doing this we'll just set it to this if our raw movement input dot x is over a certain threshold so we'll say mathf dot absolute value that way it doesn't matter if we're moving left or right and to this we will pass raw movement input dot x and we'll say if this is greater than let's say 0.5 f then we want to do this else we'll just set our normalized input x to zero so norm input x equals zero we can then do the same for our y input if math f dot abs raw movement input dot y is greater than 0.5 f then we want to set it to this and then again else normalized input y equals zero and that should stop that from happening so if we try with controller we jump up grab the wall and if we just give x input nothing happens until we move the stick far enough down then we'll start climbing or falling perfect so now we have our wall slide wall grab and wall climb working that means we've done everything that we needed to do for our touching wall state and we're in the perfect position to move on to our wall jump state in the next episode so yeah that's gonna do it for this episode i hope you guys are excited to move forward with the wall jump i certainly am and so before i go i just like to give a huge thank you to all of my supporters and wonderful people over on patreon and a huge special thank you to triac cody lee pyro says and miguel gray for your support on patreon you guys are awesome and i hope you guys all have a wonderful day
Info
Channel: Bardent
Views: 6,137
Rating: undefined out of 5
Keywords: Unity., tutorial, player, 2D, platformer, walljumping, wall sliding, jumping, Unity, Animation, ground, check, physics2d, castcirlce, variable, jump, height, Wall, Jumping, Movement, improvement, user, friendly, code, 2019, 2019.2.0f1, Ledge, climb, dead, cells, system, easy, beginner, animation, Dash, Ghosting, After, Image, After Image, Unity combat, Comabt, Melee, Melee Combat, Basic, Enemy, Patrol, State, Machine, respawn, hit, finite state maching, state machine, enemy, behavior, Archer, FSM, New, Input
Id: hKMjG3Lyf5c
Channel Id: undefined
Length: 38min 31sec (2311 seconds)
Published: Sat Aug 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.