Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Mario Style Jumping?

Discussion in '2D' started by AV_Corey, Jan 25, 2016.

  1. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    I've looked everywhere and cannot find how to get a Mario style jump mechanic in C#.

    By a Mario style jump I mean you can tap the jump key and the player will do a little hop and if you hold it they will perform a higher jump. I'm very new to programming and didn't want to bother you professionals with this probably simple question but this is my last resort.
     
  2. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    I wrote this for you. It is heavily commented and should explain everything, so as long as you are here to learn it should get you to a good starting point.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class NewBehaviourScript : MonoBehaviour
    5. {
    6.     /*these floats are the force you use to jump, the max time you want your jump to be allowed to happen,
    7.      * and a counter to track how long you have been jumping*/
    8.     public float jumpForce;
    9.     public float jumpTime;
    10.     public float jumpTimeCounter;
    11.     /*this bool is to tell us whether you are on the ground or not
    12.      * the layermask lets you select a layer to be ground; you will need to create a layer named ground(or whatever you like) and assign your
    13.      * ground objects to this layer.
    14.      * The stoppedJumping bool lets us track when the player stops jumping.*/
    15.     public bool grounded;
    16.     public LayerMask whatIsGround;
    17.     public bool stoppedJumping;
    18.  
    19.     /*the public transform is how you will detect whether we are touching the ground.
    20.      * Add an empty game object as a child of your player and position it at your feet, where you touch the ground.
    21.      * the float groundCheckRadius allows you to set a radius for the groundCheck, to adjust the way you interact with the ground*/
    22.  
    23.     public Transform groundCheck;
    24.     public float groundCheckRadius;
    25.  
    26.     //You will need a rigidbody to apply forces for jumping, in this case I am using Rigidbody 2D because we are trying to emulate Mario :)
    27.     private Rigidbody2D rb;
    28.  
    29.     void Start()
    30.     {
    31.         //sets the jumpCounter to whatever we set our jumptime to in the editor
    32.         jumpTimeCounter = jumpTime;
    33.     }
    34.  
    35.     void Update()
    36.     {
    37.         //determines whether our bool, grounded, is true or false by seeing if our groundcheck overlaps something on the ground layer
    38.         grounded = Physics2D.OverlapCircle (groundCheck.position, groundCheckRadius, whatIsGround);
    39.  
    40.  
    41.         //if we are grounded...
    42.         if(grounded)
    43.         {
    44.             //the jumpcounter is whatever we set jumptime to in the editor.
    45.             jumpTimeCounter = jumpTime;
    46.         }
    47.     }
    48.  
    49.     void FixedUpdate()
    50.     {
    51.         //I placed this code in FixedUpdate because we are using phyics to move.
    52.  
    53.         //if you press down the mouse button...
    54.         if(Input.GetMouseButtonDown(0) )
    55.         {
    56.             //and you are on the ground...
    57.             if(grounded)
    58.             {
    59.                 //jump!
    60.                 rb.velocity = new Vector2 (rb.velocity.x, jumpForce);
    61.                 stoppedJumping = false;
    62.             }
    63.         }
    64.  
    65.         //if you keep holding down the mouse button...
    66.         if((Input.GetMouseButton(0)) && !stoppedJumping)
    67.         {
    68.             //and your counter hasn't reached zero...
    69.             if(jumpTimeCounter > 0)
    70.             {
    71.                 //keep jumping!
    72.                 rb.velocity = new Vector2 (rb.velocity.x, jumpForce);
    73.                 jumpTimeCounter -= Time.deltaTime;
    74.             }
    75.         }
    76.  
    77.  
    78.         //if you stop holding down the mouse button...
    79.         if(Input.GetMouseButtonUp(0))
    80.         {
    81.             //stop jumping and set your counter to zero.  The timer will reset once we touch the ground again in the update function.
    82.             jumpTimeCounter = 0;
    83.             stoppedJumping = true;
    84.         }
    85.     }
    86. }
     
    twomack37 likes this.
  3. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    I haven't tried this yet but I can't explain how grateful I am for you to have gone and wrote all of that for me. >.< Thanks so much man.
     
    irhee630 likes this.
  4. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    It's no big deal. Most of it I just copy/pasted from existing scripts I am using and just deleted all the irrelevant stuff.

    Hope it helps!
     
  5. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    I just tried it out... Hey do you wanna get married?
     
    topherbwell likes this.
  6. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    heh nice I'll take it that it worked out then? great!
     
    AV_Corey likes this.
  7. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    It is all working perfectly apart from sometimes it will just eat the button input and not jump. I'm suspecting it's something to do with the groundCheck Radius or the groundCheck box collider attatched to my player but I'm not too sure. Have you seen this behaviour in the project you're using this code with?
     
  8. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Wouldn't advise putting the sensor for jumping in FixedUpdate. Makes for laggy gameplay
     
    cferry322 and MoonJellyGames like this.
  9. MoonJellyGames

    MoonJellyGames

    Joined:
    Oct 2, 2014
    Posts:
    331
    And I wouldn't advise controlling your 2D platformer character with the physics engine (rigidbody2D, applying force, setting velocity, etc). Raycasting is, in my experience, a much better way to go.
     
  10. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Done right, using 2D physics is totally fine, you get a slew of advantages doing everything in the physics system, it's just another way of approaching things. 2D platformers try to emulate physics so why not use a physics engine if you have one? ;)
     
    theANMATOR2b likes this.
  11. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    here's how I go about it, I'll show the theory:

    Update - grab input.

    Fixed Update - add continuous forces.

    Functions - impulse forces.

    So, for example, if you jump and want an extended jump with the button held down:
    1. Listen for jump input in Update.
    2. Make sure the player is grounded and not holding down the jump key from his/her previous jump (set a flag when landed).
    3. Fire an impulse of minimum jump force using a function.
    4. if the button is held down, keep adding some small force in Fixed update, gravity, mass and this will work together to make a max height.
    5. check for apex of jump and switch to falling when the player's Y movement becomes negative
    6. check to see if the player landed and when they release the jump key set a flag to allow for jump input once again.
     
    Last edited: Jan 26, 2016
    anchit759 likes this.
  12. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Don't put a collider on the groundCheck object. Just an empty game object (a Transform)as a child of the player is all that is needed. I suspect if you are not jumping occasionally it has to do with the positioning/radius of the ground check.

    Insert the following function into your code to visualize the radius and position of the ground check in the scene view.
    Code (CSharp):
    1. void OnDrawGizmos()
    2.     {
    3.         Gizmos.DrawSphere(groundCheck.position, groundCheckRadius);
    4.     }
     
    Last edited: Jan 26, 2016
  13. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Just to add to the discussion, you might find this article interesting. It shows 3 different ways to approach animation for a 2D game. The jumps are like you describe: holding the jump key produces a higher jump It also covers double-jumping (allowing the player to do one extra jump while in the air, but not more than that).
     
  14. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    Thanks for the explanation man, it is a big help :D
     
  15. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    Aha, I just moved everything from the FixedUpdate() into the Update() part of the script and it seems to be working fine now... Also I hate to be an ass but would you have any idea how to add a double jump into this code? Last time I had a double jump I used an int for TotalJumps, an int for currentJumps and a bool for whether or not the player canJump. I'm not too sure how I would implement this into the current code though.
     
    Last edited: Jan 26, 2016
  16. MoonJellyGames

    MoonJellyGames

    Joined:
    Oct 2, 2014
    Posts:
    331
    That seems like a reasonable way of doing it. I'd have an int _maxJumps and another int remainingJumps which is set to _maxJumps when you become grounded. When you press the jump button, ensure that remainingJumps > 0, do the actual jump and then decrement remainingJumps.
     
  17. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Code (csharp):
    1. if(jump && !grounded && jumpTimes < maxJumpTimes)
    2. {
    3. Jump();
    4. jumpTimes++;
    5. }
    Then reset your jumpTimes on grounded = true.
     
  18. Techn0man

    Techn0man

    Joined:
    Jun 4, 2017
    Posts:
    2
    When I tried this it just sent a bunch of error text messages that said

    "UnassignedReferenceException: The variable groundCheck of Jumping has not been assigned.
    You probably need to assign the groundCheck variable of the Jumping script in the inspector.
    UnityEngine.Transform.get_position () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/TransformBindings.gen.cs:27)
    Jumping.Update () (at Assets/Jumping.cs:37"
    and it placed my charater like what? 10 units up? or 5 :/
     
  19. Techn0man

    Techn0man

    Joined:
    Jun 4, 2017
    Posts:
    2
    Just relized I'm using 3D coliders and Rigid bodies... maybe that's the cause ¯\_(ツ)_/¯
     
  20. harvtb04

    harvtb04

    Joined:
    Apr 3, 2018
    Posts:
    1
    Can you just add this to your script or do you need to make a new script?
     
  21. Tryptex

    Tryptex

    Joined:
    Jul 3, 2017
    Posts:
    13
    How to you controller the high of the longer jump?
     
  22. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Please check out my article. It's mostly about animation, but in the process I develop a controller for Mario-style running and jumping (plus a single double-jump, but you could easily take that out if it's not wanted).
     
  23. PainStone

    PainStone

    Joined:
    Apr 20, 2019
    Posts:
    4
    Hello! I am a new programmer and I need to know how to make my character jump with the last detected speed before jumping and keep that speed in the air.
     
  24. MoonJellyGames

    MoonJellyGames

    Joined:
    Oct 2, 2014
    Posts:
    331
    So you're going for an oldschool Castlevania jump then, where you can't change direction mid-air? I would think you'd just write your jump code like any other example you'll find, and in your move code, don't stop the character's movement if they're jumping.

    Sorry that's not a more detailed response. I'm very tired and about to head to bed. Hopefully that gives you something to work with. If you haven't watched tutorials on YouTube on how to do basic jumping, you should do that. :)
     
  25. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Or read the article linked right above your post. It explains and demonstrates applying your running speed to the jump, and as @MoonJelly says, if you don't want them to change speed in midair, then simply take out the code that allows them to do that.

    (Note that GamaSutra munges the code formatting a bit, but there's a demo project you can download and study.)
     
    MoonJellyGames likes this.
  26. PainStone

    PainStone

    Joined:
    Apr 20, 2019
    Posts:
    4
    I have been watching video tutorials on YouTube, but none of them comes to the solution to my problem.

    this is what i got it--->
    void Jump ()
    {
    rb2d.AddForce (new Vector2 (0, jumpForce));
    // jumpForce = rb2d.velocity;
    }
     
  27. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Don't use physics for a Mario-style game. It will only make your life harder and your game worse.
     
    MoonJellyGames likes this.
  28. Mp_768

    Mp_768

    Joined:
    Nov 19, 2019
    Posts:
    1
    So what do you recommend to do? @JoeStrout
     
  29. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    I understand this point but still disagree, you're getting the 2D physics for free so why not use it? Platformers always to great lengths to mimic 2d physics.

    I've scripted a 2d character controller over the years which is pretty much drag and drop, has physics 1:1 with super mario world. How much interest would there be from the community in this? I found the ones on the Asset store to be too complex or require too much bespoke setup.
     
  30. MoonJellyGames

    MoonJellyGames

    Joined:
    Oct 2, 2014
    Posts:
    331
    But platformers don't go great lengths to mimic (realistic) 2D physics; at least not typically. Moving platforms will be significantly easier using the physics engine, but there's a lot you'll be fighting against as a consequence. If you want to be able to change direction mid-air (as in most platformers), you'll have to deal with the issue of getting stuck against walls as you jump and apply force towards it. I remember when I first encountered this, the suggested solution was to put a frictionless material on walls... but that meant that floors would also be frictionless which causes obvious problems.

    It's been a few years since I've tried this, but I'm pretty sure these (and other) issues still stand.

    I'm curious about your SMW character controller though. I'd be very impressed if it worked properly while only using the physics engine.
     
    JoeStrout likes this.
  31. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @MoonJelly

    "It's been a few years since I've tried this, but I'm pretty sure these (and other) issues still stand."

    Note - just some thoughts - not aimed at you specifically...

    If you refer to sticking to walls, that can be handled simply by not applying force to a specific direction when wall is close/touching wall.

    If you are using physics 2D/3D system to move character, it does require you to do conditional things like force character to stop on idle state or when changing run direction, one must also decide when to react to collisions by not applying force and so on.

    Anyway I bet there will be all kinds of edge cases no matter which system is used when dealing with 3D models and not pixels, and I bet experienced platformer game guys can handle all of those.

    I've tried to use raycasting, overlap tests and physics to create character controllers - all of the solutions have some issues... it is not as simple as with pure pixel to pixel collisions with any of these, you can get all kinds of edge cases like run or fall high speed into a wedge shaped pit or corner, run over bumps without lifting into air (ground hugging), walking over spiky floor, moving platforms, slope max angles, wall jumping and sliding etc.

    Of course not all games require all possible hard to do things, so this kinds of edge cases don't even need to be handled, but just saying...
     
    MoonJellyGames and JoeStrout like this.
  32. RiddleSensei

    RiddleSensei

    Joined:
    Sep 5, 2019
    Posts:
    2
    Hi All,

    I am having an issue where the "Stopped Jumping" bool is always set as true once i jump for the first time.

    I am using getkeydown instead of mousedown:

    if (Input.GetKeyDown(KeyCode.Space) && !stoppedJumping)
    {
    if (jumpTimeCounter > 0)
    {
    rb.velocity = new Vector2(rb.velocity.x, jumpForce);
    jumpTimeCounter -= Time.deltaTime;
    }

    would anyone be able to point me in the right direction on this?
     
  33. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @RiddleSensei

    And how is this related to original question? Why not create a thread for your own question as it seems it isn't about "mario style jumping" but some issue with your setup.
     
  34. RiddleSensei

    RiddleSensei

    Joined:
    Sep 5, 2019
    Posts:
    2
    @eses

    Hi there, I had assumed as there is a code solution provided by topherbwell it was appropriate to ask questions about that code here. Particularly as I made sure to type out this code exactly as is (apart from using getkeycode instead of mousebuttondown) and OP had asked follow up questions when they had issues.
     
  35. mathieubeauvill1

    mathieubeauvill1

    Joined:
    Jul 9, 2020
    Posts:
    1
    I think the community would love to see this! I'm working on a 2D Mariolike game based on item abuse like in some SMW romhacks but I really struggle making my character feel like Mario...
     
  36. NopeHGM

    NopeHGM

    Joined:
    Nov 24, 2020
    Posts:
    1





    Hello from Russia
    eee sukablyat

    I registered here just to say thank you:) I had a bug and sometimes jumps were of different power. Thanks to your script, I will finally understand what caused the bug. THANKS! Broo!!