Search Unity

Character controller jumping after landing if key pressed in midair

Discussion in 'Scripting' started by seejayjames, Jan 27, 2020.

  1. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    Probably this is simple and been answered a bunch of times, but what's the easiest way to prevent the character controller from jumping a second time (after landing) if you press jump in midair? It seems to cache the keypress, which I don't want. Also not sure why it does this at all...? Thanks!
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The Unity input system does not have any idea whether your character is in midair or not (or even whether you have a character), so if there is caching going on it's probably in your own code. You would need to post that for anyone to figure out what you're doing.

    It's also possible that you have confused GetKey with GetKeyDown, or something analogous, and are checking whether the jump button is currently down rather than whether it changed from up to down on the current frame.
     
    Joe-Censored likes this.
  3. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    Hi, it's just the standard character controller script, I haven't modified it. It uses
    CrossPlatformInputManager.GetButtonDown("Jump");
    not GetKey or GetKeyDown. However, I did try substituting GetKeyDown using Space for jump...same issue, repeated jump if you press it again during the first jump (repeats jump AFTER landing, not double-jump in the air). Tried it with the J key too, same. This doesn't happen with any custom controller I've built in the past.

    The script works together with the Character Controller, so I wonder if something internal to that is doing the caching? I don't see anything in the script that would do it, but I certainly could have missed something.

    Otherwise, seems like a bug to me...if it's intentional, is there a way to stop it?
     
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Don't know what you mean by that. Where can I see the source code?
     
  5. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    Just put in a First Person Controller prefab ("FPSController") and open the First Person Controller script that's attached to it. If you test the game you should see the jump issue. AFAIK the Character Controller's inner workings aren't directly accessible (?).
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    I am guessing that's part of some package, plugin, or example that you have imported.
     
  7. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    It's part of the Standard Assets, yes. Which is why I'm surprised there's this bug (if it is a bug...if not, I don't see why it behaves this way).
     
  8. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    OK, in FirstPersonController.cs line 68, if the player has just pressed "Jump", the script sets a variable saying that the player wants to jump. The code that actually makes the player jump checks if they are grounded, but the code that sets the variable saying that the player wants to jump does not.

    If you don't want it to "save" your jump input for later, the easiest fix is probably to add code to the end of FixedUpdate (line 134) saying
    m_Jump = false;
    that way the input gets discarded unless it is used immediately. (You could also add some conditions to the place where the variable was set, but expressing the rules for when the player is allowed to jump in 2 different places is bad from a maintenance standpoint. I suppose you could put them into a subfunction.)
     
  9. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    That did it! Prefect, thanks so much. So in Update it gets the input and sets the variable, and the actual jumping is done in FixedUpdate, where it sets the variable back to false in the jump subroutine. BUT, during the jump, getting another input button press will set m_jump to true again, and once you land it will jump. So I set m_jump = false at the end of FixedUpdate, (line 134 as you suggested), so it's always set to false regardless of whether it does a jump or not.

    Seems like this ought to be how the script should work. The only reason why not is maybe it behaves differently with different inputs besides keyboard, so it's trying to accommodate (?) but I don't have a way to test that.

    Thanks again for your time with this, I really appreciate it!
     
  10. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    I suspect this is simply a case of Unity not polishing their examples to the extent that you would normally do with production code, because they probably view the purpose of the examples as being to illustrate how you can do things rather than as ready-made solutions you can incorporate directly into a final product.

    Note that fine-tuning the code for optimal user experience often results in it being more complicated and harder to understand, which can undermine its usefulness as an example. This change was pretty simple, but if you really wanted to make a slick platformer you might do something like queue input only for a small period of time--say, 0.1 seconds--so that if a player presses jump just a tiny bit before they land, they still jump immediately like they are probably expecting. But this would be a more complex change than the one line you just added, and if you didn't anticipate that the code would be doing this it might be tricky to figure out what's going on.

    You might also add stuff like allowing the player to jump a little bit after they walk off a cliff. The user was probably trying to jump right at the edge, but got the timing slightly wrong; allowing the jump honors the intention of the player's input and makes the game feel more responsive. (This is sometimes called "coyote time", after the road runner cartoons where the coyote runs off a cliff but doesn't fall until he looks down.) But again, this would make the example noticeably more complicated for a reason that new programmers would probably never anticipate.
     
  11. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    Excellent observations, and they gave me some great ideas!