• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by tornprince2012 · Jul 30, 2019 at 06:25 AM · 2d game2d-platformer2d-physics

Creating a delay after being grounded so the player can still jump while falling.

Hey everyone, I have a tiny problem that I can't solve ( noob at scripting, yes ).

2D platformer - jumping. While grounded check works perfectly, everyone knows that back in the old days this was a known thing : if you're falling from the edge of an object ( the one you had grounded = true a split second ago ), player can't jump and falls down to his death.

What I am trying to do is to add a very short delay between player being grounded and not being grounded anymore so that the player can still jump while he's not physically on the edge anymore.

Can anyone help me with this, please?

Here's my code if someone has a minute to spare...

 public float moveSpeed;
 private float activeMoveSpeed;

 public bool canMove;

 public Rigidbody2D myRigidBody;

 public float jumpSpeed;

 public Transform groundCheck;
 public float groundCheckRadius;
 public LayerMask whatIsGround;

 public bool isGrounded;


 private Animator myAnim;

 public Vector3 respawnPosition;

 private bool onPlatform;
 public float onPlatformSpeedModifier;

 public LevelManager theLevelManager;

 public GameObject stompBox;

 public float knockbackForce;
 public float knockbackLength;
 private float knockbackCounter;

 public float invincibilityLength;
 private float invincibilityCounter;

 public AudioSource playerJumpSound;
 public AudioSource playerHurtSound;


 // Start is called before the first frame update
 void Start()
 {
     myRigidBody = GetComponent<Rigidbody2D>();
     myAnim = GetComponent<Animator>();

     respawnPosition = transform.position;

     theLevelManager = FindObjectOfType<LevelManager>();

     activeMoveSpeed = moveSpeed;

     canMove = true;

 }

 // Update is called once per frame
 void Update()
 {

     isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);

     

     if (knockbackCounter <= 0 && canMove)
     {
         if (onPlatform)
         {
             activeMoveSpeed = moveSpeed * onPlatformSpeedModifier;
         }
         else
         {
             activeMoveSpeed = moveSpeed;
         }

         if (Input.GetAxisRaw("Horizontal") > 0f)
         //if (CrossPlatformInputManager.GetAxis("Horizontal") > 0f)
         {
             myRigidBody.velocity = new Vector3(activeMoveSpeed, myRigidBody.velocity.y, 0f);
             transform.localScale = new Vector3(1f, 1f, 1f);
         }
         else if (Input.GetAxisRaw("Horizontal") < 0f)
         //else if (CrossPlatformInputManager.GetAxis("Horizontal") < 0f)
         {
             myRigidBody.velocity = new Vector3(-activeMoveSpeed, myRigidBody.velocity.y, 0f);
             transform.localScale = new Vector3(-1f, 1f, 1f);
         }
         else
         {
             myRigidBody.velocity = new Vector3(0f, myRigidBody.velocity.y, 0f);
         }


         if (Input.GetButtonDown("Jump") && isGrounded)
         //if (CrossPlatformInputManager.GetButtonDown("Jump") && isGrounded)
         {
             myRigidBody.velocity = new Vector3(myRigidBody.velocity.x, jumpSpeed, 0f);
             playerJumpSound.Play();
         }


     }

     if(knockbackCounter > 0)
     {
         knockbackCounter -= Time.deltaTime;

         if (transform.localScale.x > 0)
         {
             myRigidBody.velocity = new Vector3(-knockbackForce * 3f, knockbackForce, 0f);
         }
         else
         {
             myRigidBody.velocity = new Vector3(knockbackForce * 3f, knockbackForce, 0f);
         }    
     }

    
     if (invincibilityCounter > 0)
     {
         invincibilityCounter -= Time.deltaTime;
     }

     if(invincibilityCounter <= 0)
     {
         theLevelManager.invincible = false;
     }


     myAnim.SetFloat("Speed", Mathf.Abs(myRigidBody.velocity.x));
     myAnim.SetBool("Grounded", isGrounded);

     if(myRigidBody.velocity.y < 0)
     {
         stompBox.SetActive(true);
     }
     else
     {
         stompBox.SetActive(false);
     }

 }
 public void Knockback()
 {
     knockbackCounter = knockbackLength;
     invincibilityCounter = invincibilityLength;
     theLevelManager.invincible = true;
 }

 public IEnumerator RespawnAfterFall()
 {
     yield return new WaitForSeconds(2f);
     transform.position = respawnPosition;

 }

 private void OnTriggerEnter2D(Collider2D other)
 {
     if(other.tag == "KillPlane")
     {
         
         StartCoroutine("RespawnAfterFall");

         //gameObject.SetActive(false);

         //transform.position = respawnPosition;

         //theLevelManager.Respawn();
     }   

     if(other.tag == "Checkpoint")
     {
         respawnPosition = other.transform.position;
     }
 }

 private void OnCollisionEnter2D(Collision2D other)
 {
     if(other.gameObject.tag == "MovingPlatform")
     {
         transform.parent = other.transform;
         onPlatform = true;
     }
 }

 private void OnCollisionExit2D(Collision2D other)
 {
     if(other.gameObject.tag == "MovingPlatform")
     {
         transform.parent = null;
         onPlatform = false;
     }
 }

}

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by I_Am_Err00r · Jul 30, 2019 at 01:37 PM

First add a public float secondChanceTime (this variable will represent short delay you want, set that in the inspector) and maybe a private bool secondChance and set it default to true; then somewhere in that giant Update block (might want to break out each function into their own to make a little cleaner) add this line:

 if(isGrounded != true)
 {
 Invoke("SecondChance", secondChanceTime);
 }

Then somewhere outside of that update block add this:

 //this function can either be public or private, depends on if other scripts need to know about the secondChance change
 
 public void SecondChance()
 {
 secondChance = false;
 }

Then change jump function to something like this:

 if (Input.GetButtonDown("Jump") && secondChance == true)

And then don't forget to add something back to the isGrounded to make secondChance true again, and that will give you the short window to jump again if you fall off platform.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tornprince2012 · Jul 31, 2019 at 05:39 PM 0
Share

Thank you so much!!!

Worked like a charm after some understanding that I needed to be isGrounded once thePlayer touches the ground and can jump again. Thank you!!!!

avatar image Bunny83 · Jul 31, 2019 at 06:04 PM 0
Share

This is not really a good approach. As long as isGrounded is false you queue another SecondChance execution every frame. while this is relatively irrelevant for a single jump, if can easily produce interference when you jump in quick succession or if you loose ground contact quite frequently. A re-triggerable cooldown would be simpler, more reliable and less resource intensive.

avatar image
0

Answer by Bunny83 · Jul 31, 2019 at 06:12 PM

Just declare a cooldown / timer variable which takes care of the "signal extension".

 public float jumpTimeExtension = 0.5f;
 float jumpCondition = 0;
 
 void Update()
 {
     // [ ... ]
     if (isGrounded)
         jumpCondition = jumpTimeExtension;
     if (jumpCondition > 0)
     {
         jumpCondition -= Time.deltaTime;
         if (Input.GetButtonDown("Jump"))
         {
             myRigidBody.velocity = new Vector3(myRigidBody.velocity.x, jumpSpeed, 0f);
             playerJumpSound.Play();    
         }
     }
     // [ ... ]
 }

So while "jumpCondition" is greater than 0 you can jump. As long as you are grounded it's set to "jumpTimeExtension" every frame and therefore greater than 0. Since we subtract deltaTime each frame it naturally drops over time if it's not reset every frame. So once the time has run out you can no longer jump. As soon as you get back to ground the timer resets immediately.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tornprince2012 · Aug 01, 2019 at 12:47 PM 0
Share

Thank you for your time and effort to help!

I would agree to this because of your great explanation about doing things the "right" way resources-wise and due to its simplicity.

However, if I make that delay for jump a quarter of a second, I can squeeze 2 jumps if I am quick enough. Now - this is not my goal. I would like to keep a single jump only WHILE having that delay where player is falling down from platforms but still able to save themselves during that quarter of a second.

Is there any way to prevent any jumps after the initial one?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

145 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

OnTriggerEnter2D(Collider2D other) 2 Answers

Can anybody help me with this? Character bodying is falling apart. 0 Answers

Help Me! I want to make a pixel fairy! 1 Answer

How can I make an object stop all momentum and hold it's position in air? 1 Answer

BoxCollider2D have an offset on collision,Collider2D has an collision offset? 0 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges