How to Jump in Unity 3D: Jumping Like Mario [Built-In Character Controller #3]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Now that we know how to move and animate a  character in Unity, we want to learn how to jump!   Let’s do it! Today we are going to implement a  jump mechanic using Unity’s Built-In Character   Controller, animations and the new input system!  But jumping can be hard to get just right! So   we’ll do so trying to replicate the mechanic from  the king of jumping in video games: Super Mario! My name is Nicky and this channel is  iHeartGameDev, a channel all about   game development. The biggest shout  out to the backers over on Patreon   for not only their support but for also helping  to choose the topic! Now let’s get started! What can be said about Mario’s  Jump? Well, quite a bit, actually!   Outside of Mario’s jump “feeling” perfect during  gameplay, it consistently reaches the same height   every single time as long as the jump button  is held down. We can also see that once Mario   reaches the apex, or max height, of the jump,  he begins to fall faster! And we know that if   we let go of the jump button, it will shorten  the duration and height reached for the jump.   By slowing down the playback, we can see that  the animation transition between Mario’s idle,   walking and running states to his jumping states  is instantaneous. And, if we jump consecutively,   Mario performs alternate jump types; each  with its own animations and trajectories. And, We have a checklist of what can make  for a great jump! Let’s go through   and try to replicate each component  that we just defined to make our own   jump! By the end of this video, we’ll  have a jump that looks just like this! Opening Unity, let’s recap the previous episode of  this series to make sure we’re all starting from   the same place and have the same fundamental  understanding of what we are working with.   We have downloaded the Jammo character model  featured on the hit youtube channel: Mix And   Jam. We also went ahead and both downloaded and  retargeted animations from Adobe’s Mixamo platform   for Jammo to use. Jammo has an animator component  to control the transitions between animation   states, and a character controller component  that we use for movement and collision detection.   We’ve used the new input system  to create an input actions asset,   and within that we’ve set up an “action map” and  “actions” that currently track the player’s input   for both movement and running. And to actually  use all of that, we’ve programmed the movement,   animations, rotation and gravity for Jammo!  Be sure to check out the full tutorial to   get the complete walkthrough or you can grab  access to that project file and this episode’s   complete project file over on Patreon while also  supporting the channel. Otherwise, you can sit   back and enjoy the video by just watching to  see how we implement this version of a jump! Taking a look at our PlayerInput input action  that we created to use the new input system,   we’ll see the Character Controls action map.  Here, we currently have the “Movement” and “Run”   Actions which are how we currently  give players control of Jammo.   Let’s start by creating a new Action called “Jump”  which we’ll keep as the “Button” action type.   In our code, “Buttons” will return boolean true  or false values depending on if the player is   pressing the button or not, so we’ll be able to  use that when programming the jump logic! Next,   we’ll need to map this to a couple of buttons!  Pressing on the plus button next to the action,   we will see the option to add a new binding.  When we select this newly generated binding,   we can use the binding property to select  which button we want our jump to be set to.   And using the “Listen” option, we can just press  the spacebar for the option to be selectable.   We can also add another binding, except  for the “A” button, or “south” button,   on a controller by following that same process. Great! Let’s open up our code and begin  to program our jump implementation.   Based on the jump action that we just set up  in the editor, let’s program the jump callback   function that will keep track of whether or not  either of the assigned jump buttons are pressed.   We can do so by first creating a variable that we  will use to store the jump button’s current value.   We’ll write “the boolean  isJumpPressed is equal to false”   because by default, the player  will not be pressing this button. Next, we’ll write two callback functions  that will keep our “isJumpPressed” variable   updated to the proper value. As a reminder,  callbacks functions are executed when certain   events take place and provide “context” or “data”  for us to use from the event. So we’ll want the   callback function to be triggered when the  button is pressed and when it is released! Now, in the previous episode we also set up  callbacks as can be seen here. To properly   update our code with the player’s input, we set  the callbacks to be invoked during the “started”,   “performed” and “canceled” phases of the  player’s input. What this means is that   when a button is first pressed, the “started”  phase is triggered and our callback is run.   The “Performed” phase is typically triggered when  a player input has been completed or updated,   like an analog stick moving from left to right.  And the “canceled” phase is when the player input   has stopped that form of input, like releasing  a button. For our jump callback, we’ll only need   to know when it’s initially pressed and when it’s  released so we can use “started” and “canceled”. We’ll write “PlayerInput dot CharacterControls  dot jump dot started” which will map into   our PlayerInput input action, into  the CharacterControls action map,   select the jump action and designate that  we want to listen for the “started” phase.   We’ll then add “plus equals” passing in the  callback function that we want triggered.   We will name that callback “onJump”  and we can define that function below.   But first we will duplicate this code  and replace “started” with “canceled” Now, “onJump” will not return any value  from the function, so we can write   “void onJump which takes context of type  InputAction.CallbackContext” as an argument.   As a reminder InputAction.CallbackContext  is only available if we import the   namespace “UnityEngine dot InputSystem”,  and we have access to the PlayerInput   only because that’s what we titled the input  action asset, selected to generate a c# class   and created the instance of it within the code.  This was all fully explained last episode. Within the callback we’ll set the “isJumpPressed”  value equal to context dot readValueAsButton.   And just like that, we’ll have access to whether  the jump button is pressed from within our code!   We can test this by also logging the  value to the console just to be sure! Awesome! Now we can actually focus on learning  how our jump will work. As a disclaimer,   I am not an expert in physics, so this is going to  be my interpretation of some excellent resources   that I found when researching for this video  -- the links will be in the description! Let’s start by visualizing a character jumping.  How do we actually get them into the air? Well,   physics would say that we apply a positive force! At the start of a jump, the velocity y value  of the character will immediately bump to a   relatively high positive number one time. We can  consider this explosive force the “initial Jump   Velocity”. This point in time will actually be  the highest that the velocity y value will reach   because gravity is the constant negative   acceleration that is continuously going  to be added to the velocity y value.   What this means is that over time, the character’s  upward velocity will slow, the character will   reach the apex, or highest point, of the jump,  and then the velocity y value will proceed back   to a negative number and bring the character  back down to the ground. And that is a jump! Now, what can we take from this understanding of  jumping? If we graph out the velocity over time,   it would be represented by a descending  line because our acceleration, gravity,   is a constant negative number being added to  the velocity, and as just mentioned the initial   starting point of the jump is the highest the  velocity y value will be. If we were to track the   character’s position from a standstill, because  gravity is a constant number, we’ll find that   the trajectory maps out to be a symmetric curve  known as a “parabola”. Knowing that the arch of   the jump is a Parabola is incredibly helpful/!  The properties of a Parabola will enable us to   actually find the values of variables we’ll  need to make our character jump in our code. So what are the variables we will  need for our jump implementation?   We’ll use “Gravity” as the constant negative  acceleration, “initialJumpVelocity” that propels   our character into the air, “maxJumpHeight”  which is the maximum height we would want   our character to reach if the jump button  is held down the entire time of the jump,   and “maxJumpTime” which is the longest  length of time for the jump possible   from a standstill until it reaches the same  y position that it started at. And we’ll   also add “isJumping” which will be true or false  depending on if the player is actively jumping. Let’s go ahead and declare variables for  each of these in the scope of the class.   Each will be of type float except  isJumping will be a boolean.   And, actually, gravity is something  we set up in the previous episode,   as we’ll notice both the gravity variable  and another called groundedGravity. This additional groundedGravity variable  is used when the character is grounded,   or touching the ground. When grounded, we switch  to this smaller value, making it less likely for   the character controller to clip through the  floor from too high of a downward velocity.   We also have a function called handleGravity  that currently performs this logic,   switching between the two. But let’s take a second  to move it to the bottom of the Update function.   “handleGravity” is called inside of the Update  function which means it’s called once per frame. We’ll also notice the characterController’s “Move”   function is being called inside  the Update function as well. The   character controller’s isGrounded property  is determined by if character was touching   the ground in the last move call, which is  why we move it below where move is called. Getting back to the variables we just  declared and our new knowledge of jumping,   let’s take a look at the formulas we can use to  get our desired jump implementation. Let’s create   a new function titled “setupJumpVariables”  which we will call inside of Awake.   Now, with Parabolas, we can calculate gravity  using the following formula: “minus two times   the max height of the jump over the time to the  apex of the jump, squared”. And because we know   our jump parabolas are symmetrical, we know that  the time to the apex of the jump is one half times   the max jump time. Let’s declare a new variable,  timeToApex, which cuts the “maxJumpTime” in half. But we’ll need to know how long, in seconds, we  want this jump to take for the “maxJumpTime.”   Let’s set a default of half a second,  making the TimeToApex a quarter of a second.   We can, of course, modify this value later to   speed up or slow down the jump based  on the result and our preferences. And we’ll also need to establish the maxJumpHeight  value for the top half of this equation.   Let’s set this variable to a default value of  1. Again, we can modify this if the jump isn’t   high enough or it’s too high. Now, let’s  set the gravity variable to our equation. Ok! We have gravity, time and jump height covered.  Of our variables we need for this jump, we just   need to calculate one more: initialJumpVelocity.  We can calculate this using the equation: “two   times the maxJumpHeight over time to the apex”.  And lucky for us, we already have those values! Awesome! We have what we need to jump! And our  variables are calculated properly through science!   if you want to understand these equations a  little more. Be sure to check out the GDC talk   Math for Game Programmers: Building a  Better Jump presented by Kyle Pittman   of Minor Key Games and Gearbox. Kyle  does an amazing job elaborating and   explaining why this is such  a solid approach to jumping. We are ready to jump! Let’s write the  first iteration of our jump function:   “handleJump”. Here we will check to see if  “isJumping” is false, the characterController’s   “isGrounded” property is true and that  the “isJumpPressed” boolean is also true.   If these conditions are met, we  want to set isJumping to true   and add our initialJumpVelocity to our velocity!  Remembering from the last episode that we have the   two variables that store our possible velocities:  currentMovement and currentRunMovement, we will   want to add this initialJumpVelocity to the y  value of both! And because our handleGravity   function continuously applies gravity to  both currentMovement and currentRunMovement,   we can count on both velocities always  having the same velocity y value. Now let’s invoke handleJump at the bottom of  our update function and enter play mode to see   our current results! Success! Our character  jumps into the air and falls back down!   However, we will notice that we can only jump one  time. That’s because one of our conditions in the   handleJump function is not being met: “isJumping”  is always set to true after the first call is made   but never set back to false! In our handle  jump function, which is invoked every frame,   we can add an “else if” conditional statement that  checks if the isJumpPressed variable is false,   the isJumping variable is set to true, the  characterController’s isGrounded property is true.   If that’s the case, then we should  set isJumping back to false! Testing again, we can now see that we  are able to jump multiple times! Amazing!   There are a couple of things that we should  be clear about. The isGrounded property can   be quite finicky in my personal experience.  If the character is touching the ground,   but there is no downward velocity,  the isGrounded property will be false. Additionally, it’s about time we talk about  our current implementation of Velocity.   At this point, we can look at where we set  the currentMovement and currentRunMovement   x and y values. These values do not accelerate  or decelerate in the current implementation.   Instead they are set directly to constant numbers.  So they are fine as is. But with our gravity,   we are adding that negative value continuously  over time, meaning acceleration (or deceleration   because it’s a negative value)!  With our current implementation,   we are simply taking the currentMovement and  currentRunMovement velocity, adding gravity,   or acceleration, and modifying the position in the  CharacterController’s move function. This is known   as “Euler integration” and is quite simply the  easiest implementation that gets the job done. However, Euler integration has a main drawback:   trajectories are inconsistent  depending on the framerate!   Now we are talking about very minor differences,  but they can be the difference between a player   landing or missing a tough jump, and that can be  incredibly frustrating from a player’s standpoint,   and it’s unnecessary because we can fix  the issue quite easily with alternatives. For today, we’ll use Velocity Verlet integration  to fix the issue. With Velocity Verlet,   instead of solely adding the acceleration to  velocity when calculating the new position:   instead we store the previous velocity,  calculate the new velocity in the same   manner as Euler integration, and then we  add the old and new velocities together,   multiply by 0.5 to average them and finally  multiply by the time step, which is delta time. So the only place that we need to do this with  the current implementation is in our handleGravity   function when we are applying gravity to both the  currentMovement and currentRunMovement variables.   We’ll create a “previousYVelocity” variable  variable and set it to their current y   velocity value. Then we’ll create another  variable titled “newYVelocity”, which will   be equal to the old one plus acceleration, which  in this case is gravity, times time.deltaTime.   And with one final variable titled nextVelocity,  we’ll add them together, multiply by .5 to average   them and we’ll set the currentMovement and  currentRunMovement y values to this new value!   We’ll notice that we skipped the multiplication  by Time.deltaTime here, but that’s only because   we multiply the entire currentMovement velocity  variable in the Controller.Move method. One more change we need before we test  is back in our handleJump function.   Now we can use the same velocity verlet logic to  find the average of the previous velocity and our   initial jump velocity value. However, that gets  a little messy with our grounded gravity value.   Instead, for today, we are going  to just multiply our initial Jump   Velocity by .5 which would assume  that the previous y velocity was 0. And just like that, we have  a framerate independent jump   that will always reach the same height. Looking back at our checklist of building an  awesome jump, the next step is to modify our jump   trajectory. As mentioned, the math that we’ve  used to create our jump stems from Parabolas,   or perfectly symmetric arches, but part  of what makes Mario’s jump so great is   that it doesn’t feel particularly “floaty”  and we can control the jump’s length. Let’s   modify our jump so that it no longer is  symmetrical and feels a little weightier! Looking at our graph of position over time, we  know that up until the apex, we are considered   jumping and our character is rising. But once we  meet the peak height of the jump, the character   starts descending or falling! This is the point  where we want to start to increase gravity!   Let’s create a new variable called “isFalling”.  Because we know that at the apex, the velocity   y value is 0, we know that from that point  on, this “isFalling” variable should be true!   If the character isFalling, we’ll  want to increase the gravity.   Let’s create another variable titled  “fallMultiplier” and set it to a value of 2!   This will be used to speed up the fall! The  larger this multiplier’s value, the steeper   the second half of this graph will be and the  faster the character will return to the ground! To apply this multiplier, we can create an  additional conditional statement checking if we   are falling, and then multiply the gravity being  added to our velocity variables by the multiplier. Ok! it’s a little too quick and falls a little  too short. Let’s add another quarter of a second   and raise the height to 4. Awesome -- our  jump is really starting to feel great to use! And it would be even better if we could shorten  its length if the player releases the jump button.   Fortunately, this is fairly straightforward  after the changes we just made for falling.   The fall multiplier is waiting to be used  once the conditions are met. So for isFalling,   we’ll also check if the isJumpPressed variable is  false. Now, the fall multiplier will be applied   the moment the jump button is released and  the character will fall back down faster! If we want, we can also apply a clamp to  the velocity y value so that it caps out   at a specific maxSpeed. If the character  falls from a tremendous height in a game,   this would be helpful in preventing  the character from falling down   at an insanely high speed. But  this is completely optional. Ok! We’ll definitely have noticed that  the character’s animation is stuck   in the same animation state as the movement  state Jammo was currently in: be it idle,   walk or run. We are going to want to switch to  some jump animation when the jump takes place!   If you are new to animation, be sure to check out  my tutorial “how to animate characters in Unity3D:   animator explained” for a better  understanding of what’s to come next. Taking a look at the animator component that’s  currently attached to Jammo, we’ll see the   animation controller. Double clicking on this  will open the animator window and display our   3 different animation states that we currently  have: idle, walk and run. Our character will be   able to jump in all three of these states! Let’s  create a new animation state by right clicking,   navigating to “create state” and selecting  “empty”. Then we’ll retitle this state “Jump” We need a jump animation. While in the future,  we’re going learn how we can create our own   animations in the 3D modeling software, Blender:  Today, we’ll head over to Adobe’s Mixamo.com and   find a few animations for us to use! We’ll select  the Y Bot from the character’s tab, and then   search for the following three animations:  Female Dynamic Pose, Male Dynamic Pose,   and Stylish Flip! We’ll use the default settings  while setting the Format to FBX for Unity. Dragging these three animations into  our animations folder, we’ll select   all three and find the Rig tab in the inspector.  Here we’ll select the “animation type” and switch   to humanoid, then press apply. Our jammo  character is currently set to humanoid,   meaning we can retarget these  animations to work with Jammo!   To be sure these animations were all imported  correctly, we’ll select each individually,   and press on the “animation” tab. Here we  can verify that they are properly named.   And for the stylish flip, we are actually  going to want to modify the animation settings. We’ll select “Bake Into Pose” for the  Root Transform rotation and y Setting   to remove the root movement from the animation.  Switch to “Original” for the Based Upon setting   for root transform rotation and center of mass  for root transform y and root transform position.   And we’ll set the Root Transform Y Offset to  a value of -1 to slightly move the character   higher in the animation. Lastly, we are  going to want to modify the keyframes   of this animation because there are too many  unnecessary parts that just don’t blend well!   We’ll want to move the beginning frame to  the pose that looks closest to the a regular   standing position frame 6, and the last frame to  the moment right before impact with the ground,   frame 40. Pressing apply and this animation  is ready for use later in the tutorial! Let’s first get one of these animations working  with the jump. Back in the animator, we can select   our newly created “Jump” state. And in the  inspector, we can find the “Motion” property.   Using the circle selector, we can  find the “Female Dynamic Pose”!   And we’ll begin making transitions to and from  the animation state with all three of the other   movement states. We’ll be sure to disable “Has  Exit Time” on each of these transitions so that   the animations don’t need to finish playing  to begin the transition to the next animation.   And we’ll need to create a new  boolean animator parameter:   “isJumping”. For each transition to the  jump, we’ll want “isJumping” to be true.   And for the transitions back, not only  will we want isJumping to be false,   but we’ll need to also validate that the other  parameters match with the corresponding animation   state. So back to idle, we’ll need isRunning  and isWalking to be false. Back to walking,   isWalking to be true and isRunning to be false.  And for running, both will need to be true. Entering play mode, we’ll jump and nothing  will happen. This is because we will need   to set this animator isJumping parameter  to true and false from within our code.   We will set it to true within the  handleJump function because that’s when   we are guaranteed to start jumping. And false in  our handleGravity function when we are grounded.   Because we already have the reference to the  animator component from the previous tutorial:   we can set the isJumping boolean value  using animator dot set bool passing in   the string isJumping and the  proper true or false value.   However, we’ll create two new variables in  the scope of the class: an integer titled   “isJumpingHash” and a boolean “isJumpAnimating”.  Within our awake function we’ll set isJumpingHash   to Animator dot StringToHash passing in  “isJumping” as the argument. And now we can   replace the string version of “isJumping” with  isJumpingHash inside of the SetBool functions.   And only set isJumping to false if it’s  animating. This offers a slight performance boost! Testing in play mode and we will now  see our character switch to jumping   when the jump button is pressed! We did it! We can make slight modifications to the  transitions to and from the jump state so   that they’re more instantaneous like Mario’s.  We do this by reducing the transition duration.   Selecting the transition and opening up  the “settings” dropdown, let’s switch the   transitionDuration property to .1. This will make  the dynamic animations created from interpolating   between each animation state much faster  than before and ultimately, look smoother! Alright! Our character will now play a jump  animation every time that we jump and transition   back to the proper movement state when it lands!  Take a look at the comparison! Looks great!   But now let’s take this to the next level! As mentioned after the analysis of Mario’s jump,   we may want to create different trajectories  on consecutive jumps! To do so, we’ll need to   calculate three different gravity values and  three different initialJumpVelocity values. To implement each jump we are actually going  to refactor the code from earlier. What we’ll   do is create a new integer variable titled  “jumpCount” and we’ll set it to a value of 0.   Next, we’ll create two Dictionaries that we’ll  use to store the three initial jump velocities   and the three jump gravities. A dictionary is a  way to store specific values behind assigned keys.   You need the proper key to see what’s on the  other side. In our case, our keys will be the   integers 1, 2 or 3 which represents which jump  the player is on. So in our initialJumpVelocities   dictionaries, we’ll be able to access the  first jump’s velocity by using 1 as the key. In C# we need to declare the type of key  that we’ll be using, and the type of value   it will store. So we’ll use int and float  and then declare the variable names for each.   Then we’ll assign these to two instances  of the exact same type of Dictionaries. To add the keys and values, Dictionaries  have an Add function. We’ll calculate the new   trajectories and add them to the dictionaries  inside of our “setupJumpVariables” function.   That way these calculations occur  during the awake lifecycle phase. We know the formulas! We need to know how  long we want each jump to take, and the max   height that we want each to reach. Let’s say  our first jump remains the same, our second   jump adds a value of 2 to the original height and  is 25% longer in time. We’ll plug these into our   equations and assign them to new variables called  secondJumpGravity and secondJumpInitialVelocity.   Then we’ll create a third jump that adds a value  of 4 to the original height and is 50% longer!   We’ll assign these results to variables titled  thirdJumpGravity and thirdJumpInitialVelocity. Next, we’ll add 7 lines of code.  The first three assign the first,   second and third initialJumpVelocity values  to the initialJumpVelocities dictionary.   And the last four will assign the  jumpGravities with the proper 1 2   or 3 keys and an additional key  of 0 for when JumpCount resets. So what does this do for us? Well, now all we  need to do to change the trajectory of the jump   is replace our initialJumpVelocity with the  initialJumpVelocities dictionary and key in   with the currentJumpValue. This is done by placing  that variable in brackets next to the Dictionary.   And we’ll do the same in handleGravity where  we are currently using the gravity variable. One thing to note is that we  need to increment the jump.   We would do so in the same handleJump  function if the conditions to jump are met.   So we’ll add jumpCount += 1. But to reset  the value is going to be a little different. Mario appears to have some form of timer  that counts down the moment that he lands   each jump. If we wait too long, he  just does his normal jump again.   For this, we’re going to try to  use what’s known as a coroutine. A coroutine is a function that, put simply,  is able to pause its execution for a certain   amount of time. Let’s write this coroutine  function: typing “IEnumerator jumpResetRoutine”.   IEnumerator being the return value for coroutines,  we’ll type in “yield return new WaitForSeconds”   and pass in a value of .5. What this means is that  when the coroutine is called, the first thing that   will happen is that the function will pause for  half a second before continuing to execute the   rest of the code! So after that half a second,  we can reset the jumpCount to a value of 0! And we’ll want to use this coroutine when we land.   So in the isJumpAnimating conditional of the  handleGravity function, we’ll write StartCoroutine   passing in the invoked jumpResetRoutine  function! This is proper syntax for coroutines. However, what if we don’t want to reset the  jumpCount value because the jump button was   pressed before that half a second countdown?  We can actually cancel the coroutine! We’ll need to refer to this coroutine  specifically, so we can declare a new   Coroutine variable in the scope of the  class titled “currentJumpResetRoutine”   and we will set this equal to our  StartCoroutine code in handleGravity. So at the start of our jumpConditional,  we’ll say if the jumpCount is less than 3   and currentJumpResetRoutine is not equal to  null, then we’ll StopCoroutine and pass in   currentJumpResetRoutine! We only do  this if the jumpCount is less than 3   because we would otherwise want to reset the  value restarting the jump sequence anyway! Testing in play mode and Jammo is now  jumping at 3 different heights as long as   the jump is pressed within the correct timing!  Otherwise we’ll see that it resets! Perfect! Last but not least, we are going  to need to modify our animator.   We’ll go ahead and delete the jump animation  state, right click and select “create sub state   machine”. What this does is allow us to more  cleanly transition between our jump animations   and the three movement animations. We’ll  go ahead and create the same transitions to   the jump state machine that are dependent  on the “isJumping” condition being true,   disable hasExitTime, and this time, we’ll set  the transition duration to 0 for a snappier jump! DoubleClicking on the JumpState state machine node  will navigate us into that state. Here, the big   difference is that we can lead back to the parent  state which has our three movement animations.   Let’s create 4 empty animation states.  The first is going to be the router and   it won’t even have an animation. This is our  default state when entering the jump sub state.   We’ll then set each jump animation to  the three other empty animation states. Setting up transitions from the router to each  jump state, we’ll disable has exit time and   set the transitionDuration again to 0. And now  we’ll need a new parameter that will determine   which jump animation to play. We’ll create a new  integer parameter titled “jumpCount”. For the   second and third jump animations, jumpCount  needs to be equal to 2 and 3 accordingly.   For the first, we’ll want it to be  not equal to 2 and not equal to 3.   This serves as a default animation in  case our jumpCount ever surpasses 3. Selecting that third animation where the character  flips, we’re going to want to modify the playback   speed so that the animation can be complete  even if the player lets go of the jump button   and shortens the jump. Let’s try setting it  to a value of 1.5 and see how that turns out. Lastly, we’ll want to create transitions  from each of these three jump animations   and connect them back to the Base Layer node.  But we’ll be given the option to select which   movement animation state from the base layer  we want to transition to. As it turns out,   we’ll want each of these three jump animations  to potentially transition to all three of the   movement states depending on the conditions. So  we’ll create 9 transitions, 3 per jump state,   disable has exit time, modify the settings and  assign each with its own set of conditions for   the transition to take place. We’ll use .1 again  just like before for the transition duration.   isRunning and isWalking will need to be  true and isJumping will need to be false   for the transitions from all three  of the jump states to the run state   in the base layer. isWalking will need  to be true and isRunning and isJumping   false to transition from all three  jumping states to the walking state.   And all three will need to be false  to transition back to the idle state. This offers the cleanest transition directly  back to the proper state rather than just   starting at idle and working back to the  running state if the character is running. And the very last thing we’ll need to do is  set this jumpCount value in our code! We can   do so by creating a new hash just like before:  “JumpCountHash” and set it inside of the Awake   function using the StringToHash function. In our  handle gravity function, we’ll check to see if the   jumpCount is equal to 3 when we are grounded, if  so we’ll reset to 0 and set that in the animator.   And in handle jump, we’ll set the animator  immediately after incrementing the jump count! After all of that work! Here is  our final result for this project!   Awesome job! There’s definitely smaller changes  that could make this better, but this is such   a solid starting point for a jump mechanic. Of  course, you can modify this and refactor however   you see fit! But I hope this has been a helpful  walkthrough of how to make an awesome jump! If you want to help vote on what we’ll cover  next, dashing or strafing animations, be sure   to check out the Ultra Supporter and Believer tier  on Patreon! We’d also love to have you as a part   of this awesome growing community, we’d love to  have you in the iHeartGameDev channel discord.   For updates on the next video, be sure to follow  me on twitter. Links are in the description.   But that’s all for today, thank you so much for  watching and I’ll see you in the next video!
Info
Channel: iHeartGameDev
Views: 19,615
Rating: undefined out of 5
Keywords: How To Jump in Unity3D, Jumping Like Mario, Built-In Character Controller, How to Jump in Unity, Velocity Verlet Jumping, How to move in Unity 3D, Jumping Tutorial Unity, unity3d jumping tutorial, mario jumping in unity, how to jump like mario in unity, jump in unity3d, unity jumping tutorial, animated jump in unity, jumping in unity3d, mario style jump unity, jump tutorial unity, character controller gravity, velocity verlet, velocity verlet unity, how to code jumping unity
Id: h2r3_KjChf4
Channel Id: undefined
Length: 33min 18sec (1998 seconds)
Published: Sun Jul 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.