Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Help, Player Jumping higher when moving

Discussion in '2D' started by saldor19, Sep 3, 2023.

  1. saldor19

    saldor19

    Joined:
    Sep 14, 2021
    Posts:
    3
    Hi, I got this problem in a simple 2D Player Movement script when jumping while moving horizontally. The player would jump almost double the height when sometimes, almost always. I've only got this one script and a 2D physics material and I can't really spot the issue. Please Help. I'am using this script for another project and got the same problem.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlatformMovement2D : MonoBehaviour
    6. {
    7.     [Header("References")]
    8.     public LayerMask groundMask;
    9.     Rigidbody2D rb2d;
    10.     Collider2D box2D;
    11.  
    12.     [Header("Input")]
    13.     public KeyCode jumpKey;
    14.  
    15.     [Header("Horizontal Movement")]
    16.     public float acceleration;
    17.     public float maxSpeedIdle;
    18.     public float groundFriction;
    19.     public float airFriction;
    20.     bool changingDirection => (input.x > 0 && rb2d.velocity.x < 0) || (input.x < 0 && rb2d.velocity.x > 0);
    21.     public float minimunSpeedDifferenceToApproach;
    22.     public float speedApproachTimePerUnit;
    23.  
    24.     [Header("VerticalMovement")]
    25.     public float groundCheckExtraDistance;
    26.     public float jumpImpulse;
    27.     public float jumpCooldown;
    28.     public float fallGravityMultiplier;
    29.     public float lowJumpGravityMultiplier;
    30.  
    31.     [Header("Debug")]
    32.     [SerializeField] Vector2 input;
    33.     [SerializeField] float maxSpeed;
    34.     [SerializeField] bool grounded;
    35.     [SerializeField] float jumpCooldownTimer;
    36.  
    37.     void Start()
    38.     {
    39.         //Get Components
    40.         rb2d = GetComponent<Rigidbody2D>();
    41.         box2D = GetComponent<Collider2D>();
    42.  
    43.         //Set Initial Max Speed
    44.         maxSpeed = maxSpeedIdle;
    45.     }
    46.  
    47.     void Update()
    48.     {
    49.         //Get Input
    50.         GetInput();
    51.  
    52.         //Timers
    53.         if (jumpCooldownTimer > 0) jumpCooldownTimer -= Time.deltaTime;
    54.  
    55.         //Jump
    56.         if (grounded && Input.GetKey(jumpKey) && jumpCooldownTimer <= 0)
    57.         {
    58.             Jump();
    59.             jumpCooldownTimer = jumpCooldown;
    60.         }
    61.     }
    62.  
    63.     void FixedUpdate()
    64.     {
    65.         GroundCheck();
    66.         Movement();
    67.  
    68.         if (grounded)
    69.         {
    70.             GroundFriction();
    71.         }
    72.         else
    73.         {
    74.             AirFriction();
    75.             GravityControl();
    76.         }
    77.     }
    78.  
    79.     void GetInput(){
    80.         //Vector containing Horiozntal and Vertical input
    81.         input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    82.     }
    83.  
    84.     void GroundCheck(){
    85.         //Raycast to ground check
    86.         RaycastHit2D hit2D = Physics2D.Raycast(transform.position, Vector2.down, box2D.bounds.extents.y + groundCheckExtraDistance, groundMask);
    87.         grounded = hit2D.collider != null;
    88.     }
    89.  
    90.     void Movement(){
    91.         //Apply Acceleration
    92.         if(input.x != 0) rb2d.AddForce(Vector3.right * input.x * acceleration);
    93.  
    94.         //Limit Velocity
    95.         Vector2 vel = rb2d.velocity;
    96.         vel.y = 0f;
    97.         if(Mathf.Abs(rb2d.velocity.x) > maxSpeed) rb2d.velocity = new Vector2(Mathf.Sign(rb2d.velocity.x) * maxSpeed, rb2d.velocity.y);
    98.     }
    99.  
    100.     void GroundFriction(){
    101.         //If not moving or changing directions apply ground friction
    102.         if(changingDirection || Mathf.Abs(input.x) < .4f) rb2d.drag = groundFriction;
    103.         //If moving not apply friction
    104.         else rb2d.drag = 0f;
    105.     }
    106.  
    107.     void AirFriction()
    108.     {
    109.         rb2d.drag = airFriction;
    110.     }
    111.  
    112.     public void SpeedChange(float maxSpeed){
    113.         //Difference is very little don't approach, set instantly
    114.         if(Mathf.Abs(this.maxSpeed - maxSpeed) < minimunSpeedDifferenceToApproach) this.maxSpeed = maxSpeed;
    115.         else{
    116.             //If difference in speeds is above minimun start approach
    117.             StopAllCoroutines();
    118.             StartCoroutine(SpeedChangeOverTime(maxSpeed));
    119.         }
    120.     }
    121.  
    122.     public IEnumerator SpeedChangeOverTime(float maxSpeed){
    123.         float startSpeed = this.maxSpeed;
    124.         float approachTime = Mathf.Abs(this.maxSpeed - maxSpeed) * speedApproachTimePerUnit;
    125.  
    126.         float timer = 0;
    127.  
    128.         while(timer < approachTime){
    129.             //Linear Interpolation
    130.             maxSpeed = Mathf.Lerp(startSpeed, maxSpeed, timer/approachTime);
    131.  
    132.             yield return null;
    133.  
    134.             timer += Time.deltaTime;
    135.         }
    136.  
    137.         this.maxSpeed = maxSpeed;
    138.     }
    139.  
    140.     void Jump(){
    141.         //Set vertical speed to zero
    142.         rb2d.velocity = new Vector2(rb2d.velocity.x, 0f);
    143.  
    144.         //Apply Impulse
    145.         rb2d.AddForce(Vector2.up * jumpImpulse, ForceMode2D.Impulse);
    146.     }
    147.  
    148.     void GravityControl(){
    149.         //When Falling
    150.         if (rb2d.velocity.y < .3f) rb2d.gravityScale = fallGravityMultiplier;
    151.         //When Jumping But Stop pressing jump button
    152.         else if (rb2d.velocity.y > .3f && !Input.GetKey(jumpKey)) rb2d.gravityScale = lowJumpGravityMultiplier;
    153.         else rb2d.gravityScale = 1f;
    154.     }
    155. }
    156.  
    The script is highly commented, the functions SpeedChange and SpeedChangeOverTime are not used at all. The player script's paired with a 2D Rigidbody Controller and a 2D Circle Collider.

    And the values I'm using are:

    upload_2023-9-3_16-3-50.png

    Thanks a lot in advance,

    Salvador Rodriguez :)
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    Do you understand that Update can run many times inbetween FixedUpdate running; assuming physics is set as the default of running during the Fixedupdate?

    If you're holding the jump key, you continually add an impulse. That won't be actioned until the physics simulation runs. If you have 2 or 200 frames run before the FixedUpdate, you'll be adding a lot of impulses.

    Your ground-check runs during the FixedUpdate so that won't stop you continually jumping either; note that it would matter as nothing in physics is moving until the simulation happens.

    You canuse GetKeyDown to check if you pressed it during that frame but this doesn't help if you press it really fast inbetween FixedUpdate running (not that likely TBH).

    Typically you'd flag that you want to jump and then action it in the FixedUpdate.

    Note: A much better way to detect if you're grounded is to ask the physics system if you're touching something i.e. you are in contact. This is demonstrated here:
     
  3. saldor19

    saldor19

    Joined:
    Sep 14, 2021
    Posts:
    3
    Hi MelvMay, Thanks for your reply,

    I understand it and I've a cooldown for the jump. I've tried to flip the order between lines 58 and 59 so the cooldown is set before any physical action related to jump occurs. I've also taking account of your reply and change the line 56 from Input.GetKey(jumpKey) to Input.GetKeyDown(jumpKey) just to experiment if it changes anything, but it remains the same. And I don't think it can be jump Impulse adding up a lot of impulse because the height distance is pretty the same when jumping and moving in contrast when only jumping. I've also tried with the flag you mentioned. I can't test changing the ground check to a contact of the physics engine instead of raycasting now because I've got to go to work. But as soon as I do it I'll post the results here.

    Anyway, thanks a lot for your reply, It really illuminated about some things, especifically the ground check using the physics engine you mentioned and the use of a jump flag.

    Salvador Rodriguez
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    Well also you're reading input in the FixedUpdate which is a no-can-do. Saying you tried it and it didn't fix it doesn't mean what you're doing is correct.

    Because you're using the linear drag as ground-friction and you don't use that when it thinks you're not grounded, then you're likely finding that it's jumping higher because there's little/no drag. The logic above would suggest that it thinks it's grounded so is applying that ground friction which is changed according to movement:
    Code (CSharp):
    1.     void GroundFriction(){
    2.         //If not moving or changing directions apply ground friction
    3.         if(changingDirection || Mathf.Abs(input.x) < .4f) rb2d.drag = groundFriction;
    4.         //If moving not apply friction
    5.         else rb2d.drag = 0f;
    6.     }
    I mean, you'd see that you can move in the air. This could be caused by layers not assigned correctly etc.

    It's more likely that it's not jumping higher when moving, it's likely it's the oppose, it's not jumping according to the impulse because the linear drag is so high.

    In the end, you've got to debug your logic as there's a lot of gravity and linear drag manipulation going on making it all confusing and likely prone to error.
     
  5. saldor19

    saldor19

    Joined:
    Sep 14, 2021
    Posts:
    3
    Thanks MelvMay, I re made it with your advisement from zero and it worked.
     
    MelvMay likes this.