Search Unity

[Solved] When jumping, how to use current x-velocity at time of jump but don't allow air control?

Discussion in 'Scripting' started by tfishell, Jul 20, 2018.

  1. tfishell

    tfishell

    Joined:
    Nov 20, 2017
    Posts:
    97
    I'm experimenting with a 2D platformer (including using a premade character controller script that I'm customizing for myself).

    I don't want the player to be able to control the character in air, but I do want the current x-velocity to be stored and used when the AddForce is applied for the jump. The x-velocity thus won't change until the player has landed again.

    The problem is the x-velocity is reset to 0f when the character jumps, so he'll only jump straight up (and again I want his jump to take the current horizontal speed - at the time of jumping - into effect and to not again until he lands again)

    gif of the problem (no horizontal movement maintained when jumping): https://imgur.com/a/fSOz1XW

    I assume it isn't because the AddForce's Vector2.x has an effect of 0f; that should just add 0f to the current x-velocity, right? (It's weird because if I add in a horizontal Force - like rb.AddForce(new Vector2(0f, jumpForce)); - that movement happens in a single instant/frame whereas the vertical force doesn't - https://imgur.com/a/ck8ZGy3.)

    Checking Debug.Log of x, it doesn't seem like the x velocity actually reaches 0 when jumping, but obviously visually there's only vertical movement when jumping, no horizontal.

    Would horizontal movement stop because the isGrounded bool would be false and preventing that portion of code from running?

    Relevant code (I did gut a bit because it seemed irrelevant to this problem) (the most important is the Move method at the bottom):

    edit: doing
    Code (CSharp):
    1. public void Move()
    2.     {
    3.         if (jump)
    4.         {
    5.             rb.AddForce(new Vector2(500f, 0f));
    6.         }
    7.  
    8.     }
    works fine (other than the force continuing because there's nothing stopping it), so there's something up with the bools doing some unwanted gatekeeping I guess.
    /edit

    Code (CSharp):
    1.  
    2. //--- set the control associations
    3. void Update()
    4. {
    5.     //constantly get the button states
    6.     move = Input.GetAxis("Horizontal");
    7.  
    8.     if (Input.GetButtonDown("Jump")) //avoid inconsitant jumping this way
    9.     {
    10.         jump = true;
    11.         Debug.Log("jump");
    12.     }
    13.  
    14.     if (isGrounded)
    15.         crouch = Input.GetButton("Crouch");
    16.     else
    17.         crouch = false; //can't crouch if not grounded
    18. }
    19.  
    20. //--- Use FixedUpdate for physics calculations so the timing is consistant
    21. //--- or use LateUpdate to handle lines moving correctly with physics?
    22. public void FixedUpdate()
    23. {
    24.     //is the player standing up?
    25.     playerOnGroundIsPlaying = anim.GetCurrentAnimatorStateInfo(0).IsName("playerOnGround");
    26.     //is the player crouching?
    27.     playerCrouchingIsPlaying = anim.GetCurrentAnimatorStateInfo(0).IsName("playerCrouching");
    28.  
    29.     CollidersNearGroundCheck();
    30.     Move();
    31. }
    32.  
    33. public void CollidersNearGroundCheck()
    34. {
    35.     //--- colliders near groundCheck
    36.  
    37.     //store nearby colliders within the groundcheck radius in an array
    38.     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, groundCheckRadius, whatIsGround);
    39.  
    40.     //loop through array of colliders
    41.     for (var i = 0; i < colliders.Length; i++)
    42.     {
    43.         //if the current gameobject in array isn't the player
    44.         if (colliders[i].gameObject != gameObject)
    45.         {
    46.             //player is on ground, not in air
    47.             isGrounded = true;
    48.         }
    49.     }
    50.  
    51.     //if there are no ground colliders
    52.     if (colliders.Length <= 0)
    53.     {
    54.         //the player is not on the ground
    55.         isGrounded = false;
    56.     }
    57.  
    58.     //set horizontal animation based on grounded or not
    59.     anim.SetBool("Grounded", isGrounded);
    60. }
    61.  
    62. //--- handle the player movement (called from FixedUpdate)
    63. public void Move()
    64. {
    65.     //if crouching, check to see if the player can stand up
    66.     if (!crouch && anim.GetBool("Crouch"))
    67.     {
    68.         //if there's a ceiling preventing the player from getting up ...
    69.         if (Physics2D.OverlapCircle(ceilingCheck.position, ceilingCheckRadius, whatIsGround))
    70.         {
    71.             //keep the player crouching
    72.             crouch = true;
    73.             //don't allow jumping
    74.             jump = false;
    75.             //Debug.Log("crouching");
    76.         }
    77.     }
    78.  
    79.     //set whether or not the player is crouching in the animator
    80.     anim.SetBool("Crouch", crouch);
    81.  
    82.     //only control if grounded or air control is true
    83.     if (isGrounded || controlInAir)
    84.     {
    85.         //if crouching, reduce the speed by the crouchSpeed multiplier; otherwise, normal speed
    86.         move = (crouch ? move * crouchSpeed : move);
    87.  
    88.         //change the movement animation based on the move speed (whether going left or right)
    89.         anim.SetFloat("Move", Mathf.Abs(move));
    90.  
    91.         //move the player horizontally: -1 or 1 * speed multiplier, vertical speed
    92.         rb.velocity = new Vector2(move * xSpeed, rb.velocity.y);
    93.         Debug.Log(rb.velocity.x);
    94.     }
    95.  
    96.     //if player is grounded and jump button is pressed, and the Ground animator bool is true
    97.     if (isGrounded && jump)
    98.     {
    99.         //add a vertical force to the player (jump)
    100.         rb.AddForce(new Vector2(0f, jumpForce));
    101.         isGrounded = false;
    102.         jump = false; //set jump to false here so that there aren't "skips" in jumping
    103.     }
    104. }
    105.  
    Thanks for any help in advance.
     
    Last edited: Jul 20, 2018
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,744
    Might it be line 92 setting your x-velocity directly? I'm speculating that you do your jump, your isGrounded turns to false, but the next frame your "overlap check" code says you're grounded again possibly? Throw some more Debug.Logs in there to see when you collide, when you jump, etc., or just set some breakpoints.
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Have you tried reducing your rigidbody's drag value?
     
  4. tfishell

    tfishell

    Joined:
    Nov 20, 2017
    Posts:
    97
    I'll try checking it out, thanks. (tbh I've never really used breakpoints but now would be a good time)

    UPDATE: Looks like that was the issue, thanks. I tested using a raycast to only allow movement when hitting ground. I think I'll need to rework the script without using that OverlapCircleAll and just use all raycasts instead.

    The linear drag is already set to 0.
     
    Last edited: Jul 20, 2018
    Kurt-Dekker likes this.