Search Unity

How to prevent Multiple Double Jumps

Discussion in 'Scripting' started by StarShipMan, Dec 18, 2014.

  1. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91
    Hey everyone,

    This issue is driving me nuts.

    I followed the official Unity Character Controller video on Youtube and everything works fine until i got a buddy to play test the game, he started repeatedly tapping jump as opposed to just double tapping to double jump.

    The issue is the character jumps too many times (not all the time only sometimes) even though i have a bool set up to stop the player from jumping more than twice at one time. How can i go about fixing this. Please assist
    [Edit: I discovered that whenever my character touches a collider of any kind with a Trigger set to true this happenes. All other colliders without triggers does not impact jumping]

    Character Controller Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerControl : MonoBehaviour
    5. {
    6.     public float maxSpeed = 10f;
    7.     bool facingRight = true;
    8.     public bool didPlayerJump = false;
    9.  
    10.     public float float1 = 0;
    11.     public float float2 = 0;
    12.     public bool moveLeft = false;
    13.     public bool moveRight = false;
    14.     public bool wasEnemyStomped = false;
    15.  
    16.  
    17.     Animator anim;
    18.     int audioCount = 0;
    19.     public GameObject running;
    20.  
    21.     bool grounded = false;
    22.     public Transform groundCheck;
    23.     public float groundRadius = 0.2f;
    24.     public LayerMask whatIsGround;
    25.     public float jumpForce = 20f;
    26.     bool doubleJump = false;
    27.  
    28.     void Start()
    29.     {
    30.         anim = GetComponent<Animator> ();
    31.     }
    32.  
    33.     void FixedUpdate()
    34.     {
    35.         // This is the Jump code
    36.         grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
    37.         anim.SetBool ("Ground", grounded);
    38.         //This should work to prevent jumping more than double(double jump)
    39.         if (grounded)
    40.             doubleJump = false;
    41.  
    42.         anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
    43.  
    44.         //This is the Movement code
    45.         float move = Input.GetAxis ("Horizontal");
    46.  
    47.         if (float1 < 0)
    48.         {
    49.             move = -1;
    50.             if(move == - 1)
    51.             {
    52.                 Debug.Log ("Move float is -1");
    53.                 if(grounded)
    54.                 {
    55.                     moveLeft = true;
    56.                     Debug.Log ("Move Left bool is triggered");
    57.                 }
    58.             }
    59.             else
    60.                 moveLeft = false;
    61.         }
    62.  
    63.         if (float2 > 0)
    64.         {
    65.             move = 1;
    66.             Debug.Log ("Move Right is triggered");
    67.  
    68.             if(move ==  1)
    69.             {
    70.                 Debug.Log ("Move float is +1");
    71.                 if(grounded)
    72.                 {
    73.                     moveRight = true;
    74.                     Debug.Log ("Move Left bool is triggered");
    75.                 }
    76.             }
    77.             else
    78.                 moveLeft = false;
    79.         }
    80.  
    81.         if(move < 0 && audioCount == 0)
    82.         {
    83.             if(grounded)
    84.             {
    85.                 Debug.Log ("Running audio clip initiated on Left Arrow");
    86.                 running.audio.Play();
    87.                 audioCount +=1;
    88.                 Invoke ("AudioCount",0.2f);
    89.             }
    90.  
    91.         }
    92.         else
    93.             moveLeft = false;
    94.  
    95.         if(move > 0 && audioCount == 0)
    96.         {
    97.             if(grounded)
    98.             {
    99.                 Debug.Log ("Running audio clip initiated on Right Arrow");
    100.                 running.audio.Play();
    101.                 audioCount +=1;
    102.                 Invoke ("AudioCount",0.2f);
    103.             }
    104.         }
    105.         else
    106.             moveRight = false;
    107.  
    108.         anim.SetFloat ("Speed", Mathf.Abs (move));
    109.  
    110.         rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);
    111.  
    112.         if (move > 0 && !facingRight)
    113.                         Flip ();
    114.         if (move < 0 && facingRight)
    115.                         Flip ();
    116.  
    117.         }
    118.  
    119.     void Update()
    120.     {
    121.         //This controls jumping and movement
    122.         if((grounded||!doubleJump) && (Input.GetKeyDown(KeyCode.Space) || didPlayerJump || wasEnemyStomped==true))
    123.         {
    124.             Debug.Log ("didPlayerJump was activated");
    125.             anim.SetBool("Ground", false);
    126.             audio.Play ();
    127.  
    128.             didPlayerJump = false;
    129.      
    130.             rigidbody2D.AddForce(new Vector2(0,jumpForce));
    131.             wasEnemyStomped =false;
    132.      
    133.             if(!doubleJump && !grounded)
    134.             {
    135.                 doubleJump = true;
    136.                 audio.Play ();
    137.             }
    138.         }
    139.     }
    140.  
    141.     void Flip()
    142.     {
    143.         facingRight = !facingRight;
    144.         Vector3 theScale = transform.localScale;
    145.         theScale.x *= -1;
    146.         transform.localScale = theScale;
    147.     }
    148.  
    149.     void AudioCount()
    150.     {
    151.         audioCount -=1;
    152.     }
    153. }
    154.  
     
    Last edited: Dec 23, 2014
  2. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91
    After some experimenting i discovered that whenever the player is inside of any trigger within the game, it somehow allows you to do an extra jump if you pressed jump multiple times. Everywhere else in the game i can only do one double jump and once i touch the ground again it resets(which is what i want)

    Even an empty gameobject with a 2d collider that is set to a trigger causes the player to be able to make an extra jump if you stand inside the trigger area.
    Does anyone know why this is happening or how i can fix it?
     
  3. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91
    Last edited: Dec 23, 2014
  4. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91
    I had to place all of the collectibles on the same layer as my player character. This was the solution to my issue above. Thanks for GameDev/StackExchange user (McAden)
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Here is my 'JumpResolver':

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections.Generic;
    4.  
    5. using com.spacepuppy;
    6. using com.spacepuppy.Movement;
    7. using com.spacepuppy.Utils;
    8.  
    9. namespace com.apoc.Movement
    10. {
    11.  
    12.     [AddComponentMenu("Apoc/Movement/Resolver: Jumping")]
    13.     [RequireComponent(typeof(ApocMovementMotor))]
    14.     [RequireLikeComponent(typeof(IGroundingResolver))]
    15.     public class JumpResolver : SPNotifyingComponent, IDoubleJumpResolver
    16.     {
    17.  
    18.         #region Fields
    19.  
    20.         [Tooltip("Duration of time upon leaving the ground that you're still allowed to initialize a jump.")]
    21.         public float JumpInitDelay = 0.1f;
    22.  
    23.         public float JumpSpeed = 7.0f;
    24.  
    25.         public bool DoubleJump = false;
    26.         public float DoubleJumpCooldown = 0.1f;
    27.         [Tooltip("Restrict double jump to when you're at some height in your first jump. Defaults to negative infinity to allow double jump at any time.")]
    28.         public float MinimumHeightAllowDoubleJump = float.NegativeInfinity;
    29.         public float DoubleJumpSpeed = 7.0f;
    30.  
    31.         private ApocMovementMotor _motor;
    32.         private IGroundingResolver _groundingResolver;
    33.  
    34.         private float _cooldownTimer;
    35.         private bool _bDidDoubleJump = false;
    36.  
    37.         private bool _bJumpCached;
    38.         private float? _cachedJumpSpeed;
    39.  
    40.         #endregion
    41.  
    42.         #region CONSTRUCTOR
    43.  
    44.         protected override void Awake()
    45.         {
    46.             base.Awake();
    47.  
    48.             _motor = this.GetComponent<ApocMovementMotor>();
    49.             _groundingResolver = this.GetFirstLikeComponent<IGroundingResolver>();
    50.         }
    51.  
    52.         protected override void OnStartOrEnable()
    53.         {
    54.             base.OnStartOrEnable();
    55.  
    56.             Notification.RegisterObserver<GroundingResolver.LandedNotification>(this.entityRoot, this.OnLanded);
    57.  
    58.             _motor.BeforeUpdateMovement -= this.OnBeforeUpdateMovement;
    59.             _motor.BeforeUpdateMovement += this.OnBeforeUpdateMovement;
    60.         }
    61.  
    62.         protected override void OnDisable()
    63.         {
    64.             base.OnDisable();
    65.  
    66.             Notification.RemoveObserver<GroundingResolver.LandedNotification>(this.entityRoot, this.OnLanded);
    67.  
    68.             _motor.BeforeUpdateMovement -= this.OnBeforeUpdateMovement;
    69.         }
    70.  
    71.         #endregion
    72.  
    73.         #region Properties
    74.  
    75.         public bool IsCoolingDown { get { return _cooldownTimer > 0.0f; } }
    76.  
    77.         public bool DidDoubleJump { get { return _bDidDoubleJump; } }
    78.  
    79.         #endregion
    80.  
    81.         #region Methods
    82.        
    83.         public bool ApplyJump(ref Vector2 mv, bool bDesiresToJump = false)
    84.         {
    85.             if (!this.enabled) return false;
    86.             if (this.IsCoolingDown) return false;
    87.  
    88.             var t = GameTime.Time;
    89.             if (_groundingResolver.IsGrounded ||
    90.                 (t - _groundingResolver.LastJumpedTime > this.JumpInitDelay && t - _groundingResolver.LastGroundedTime < this.JumpInitDelay))
    91.             {
    92.                 if (_bJumpCached || bDesiresToJump)
    93.                 {
    94.                     var spd = (_cachedJumpSpeed != null) ? _cachedJumpSpeed.Value : this.JumpSpeed;
    95.                     //mv.y = spd;
    96.                     mv = VectorUtil.SetLengthOnAxis(mv, _groundingResolver.DesiredJumpNormal, spd);
    97.  
    98.                     _bJumpCached = false;
    99.                     _cachedJumpSpeed = null;
    100.                     _cooldownTimer = this.DoubleJumpCooldown;
    101.                     return true;
    102.                 }
    103.             }
    104.             else if (this.DoubleJump && !_bDidDoubleJump)
    105.             {
    106.                 if (_bJumpCached || bDesiresToJump)
    107.                 {
    108.                     if (!_groundingResolver.IsGrounded && (_motor.Position.y - _groundingResolver.LastGroundedPosition.y) > this.MinimumHeightAllowDoubleJump)
    109.                     {
    110.                         var spd = (_cachedJumpSpeed != null) ? _cachedJumpSpeed.Value : this.DoubleJumpSpeed;
    111.                         //mv.y = spd;
    112.                         mv = VectorUtil.SetLengthOnAxis(mv, _groundingResolver.DesiredJumpNormal, spd);
    113.  
    114.                         _bJumpCached = false;
    115.                         _cachedJumpSpeed = null;
    116.                         _cooldownTimer = this.DoubleJumpCooldown;
    117.                         _bDidDoubleJump = true;
    118.  
    119.                         return true;
    120.                     }
    121.                 }
    122.             }
    123.  
    124.             _bJumpCached = false;
    125.             return false;
    126.         }
    127.  
    128.         public bool ApplyJump(ref Vector2 mv, float overrideJumpSpeed, bool bDesiresToJump = false)
    129.         {
    130.             if (!this.enabled) return false;
    131.             if (this.IsCoolingDown) return false;
    132.  
    133.             var t = GameTime.Time;
    134.             if (_groundingResolver.IsGrounded ||
    135.                 (t - _groundingResolver.LastJumpedTime > this.JumpInitDelay && t - _groundingResolver.LastGroundedTime < this.JumpInitDelay))
    136.             {
    137.                 if (_bJumpCached || bDesiresToJump)
    138.                 {
    139.                     var spd = (_cachedJumpSpeed != null) ? _cachedJumpSpeed.Value : overrideJumpSpeed;
    140.                     //mv.y = spd;
    141.  
    142.                     mv = VectorUtil.SetLengthOnAxis(mv, _groundingResolver.DesiredJumpNormal, spd);
    143.                     _bJumpCached = false;
    144.                     _cachedJumpSpeed = null;
    145.                     _cooldownTimer = this.DoubleJumpCooldown;
    146.                     return true;
    147.                 }
    148.             }
    149.             else if (this.DoubleJump && !_bDidDoubleJump)
    150.             {
    151.                 if (_bJumpCached || bDesiresToJump)
    152.                 {
    153.                     if (!_groundingResolver.IsGrounded && (_motor.Position.y - _groundingResolver.LastGroundedPosition.y) > this.MinimumHeightAllowDoubleJump)
    154.                     {
    155.                         var spd = (_cachedJumpSpeed != null) ? _cachedJumpSpeed.Value : overrideJumpSpeed;
    156.                         //mv.y = spd;
    157.  
    158.                         mv = VectorUtil.SetLengthOnAxis(mv, _groundingResolver.DesiredJumpNormal, spd);
    159.                         _bJumpCached = false;
    160.                         _cachedJumpSpeed = null;
    161.                         _cooldownTimer = this.DoubleJumpCooldown;
    162.                         _bDidDoubleJump = true;
    163.  
    164.                         return true;
    165.                     }
    166.                 }
    167.             }
    168.  
    169.             _bJumpCached = false;
    170.             return false;
    171.         }
    172.  
    173.         public void CacheJump()
    174.         {
    175.             if (this.IsCoolingDown) return;
    176.  
    177.             _bJumpCached = true;
    178.             _cachedJumpSpeed = null;
    179.         }
    180.  
    181.         public void CacheJump(float overrideJumpSpeed)
    182.         {
    183.             if (this.IsCoolingDown) return;
    184.  
    185.             _bJumpCached = true;
    186.             _cachedJumpSpeed = overrideJumpSpeed;
    187.         }
    188.  
    189.         public void SignalJumping()
    190.         {
    191.             _groundingResolver.SetJumping();
    192.             Notification.PostNotification<JumpedNotification>(this, new JumpedNotification(_bDidDoubleJump), true);
    193.         }
    194.  
    195.         public void ResetDoubleJump()
    196.         {
    197.             _bDidDoubleJump = false;
    198.         }
    199.  
    200.         public void ResetCooldown()
    201.         {
    202.             _cooldownTimer = 0.0f;
    203.         }
    204.  
    205.         #endregion
    206.  
    207.         #region Notification Handlers
    208.  
    209.         private void OnLanded(GroundingResolver.LandedNotification n)
    210.         {
    211.             this.ResetCooldown();
    212.             this.ResetDoubleJump();
    213.         }
    214.  
    215.         #endregion
    216.  
    217.         #region IMovementEnhancer Interface
    218.  
    219.         private void OnBeforeUpdateMovement(object sender, System.EventArgs e)
    220.         {
    221.             if (_cooldownTimer > 0f)
    222.             {
    223.                 _cooldownTimer -= GameTime.DeltaTime;
    224.                 if (_cooldownTimer < 0.0f)
    225.                 {
    226.                     _cooldownTimer = 0.0f;
    227.                 }
    228.             }
    229.         }
    230.  
    231.         #endregion
    232.  
    233.     }
    234.  
    235. }
    236.  

    In it I jump if on ground, or if a 'didDoubleJump' flag hasn't been set true. If NOT grounded, and a jump occurs, then I flag 'didDoubleJump' to true so we can't do it again.

    Whenever the player lands, I reset said flag to false, so we can double jump again.
     
  6. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91
    @lordofduct Thanks for your reply. I was able to solve the issue with just placing all of my colliders on the same layer as the player. I wanted to kick myself due to how easy the solution was. Think others reading this post will find your solution helpful as well.
     
  7. StarShipMan

    StarShipMan

    Joined:
    Jan 28, 2014
    Posts:
    91