I’m new to programming and after watching some tutorial’s I’ve been able to code a Character Controller.
Everything works fine except for the fact that the double jump is very inconsistent. Sometimes it will work and other times the double jump won’t occur at all. This is frustrating because I can’t seem to find anyone with a similar issue and therefor no answer. Here is the Character Jump Function and relevant code: (Note: CheckGrounded() is from a separate script that my Controller is inheriting from. This code is at the bottom.
public KeyCode jumpKey = KeyCode.Space;
private bool doubleJump;
void Update()
{
GetInput();
HandleJump();
}
private void GetInput()
{
attemptJump = Input.GetKeyDown(jumpKey);
}
private void HandleJump()
{
if (CheckGrounded())
{
coyoteTimeCounter = coyoteTime;
}
else
{
coyoteTimeCounter -= Time.deltaTime;
}
if (attemptJump)
{
if (coyoteTimeCounter > 0f || doubleJump)
{
Rb2D.velocity = new Vector2(Rb2D.velocity.x, jumpForce);
doubleJump = !doubleJump;
FindObjectOfType<AudioManager>().Play("Jump");
}
}
if (Input.GetButtonUp("Jump") && Rb2D.velocity.y > 0f)
{
Rb2D.velocity = new Vector2(Rb2D.velocity.x, Rb2D.velocity.y * 0.5f);
coyoteTimeCounter = 0f;
}
}
The inconsistency with the double jump could be caused by the coyoteTimeCounter variable not being reset properly. It appears that coyoteTimeCounter is used to allow the player to jump even if they are slightly off the ground, but only for a short amount of time after leaving the ground. If coyoteTimeCounter is not being reset properly, it could prevent the player from performing a double jump even when they should be able to.
You can try resetting the coyoteTimeCounter to its initial value when the player jumps, like this:
if (attemptJump)
{
coyoteTimeCounter = 0f; // reset coyoteTimeCounter when jumping
if (CheckGrounded() || doubleJump)
{
Rb2D.velocity = new Vector2(Rb2D.velocity.x, jumpForce);
doubleJump = !doubleJump;
FindObjectOfType<AudioManager>().Play("Jump");
}
}
This will ensure that the coyote time window is reset when the player jumps, allowing them to perform a double jump if they are still within the coyote time window.
Another potential issue could be with the doubleJump variable not being reset properly. It’s hard to tell without seeing more of the code, but make sure that doubleJump is being reset to false when the player lands on the ground or performs a double jump.
Your script seems to be very… almost professional when that may be causing an error on its own.
You have multiple functions when honestly one or two would suffice.
To demonstrate how I would code this:
if (Grounded == true)
{
if (Input.GetKey(KeyCode.Space))
{
Jumping = true;
FirstJumpMethodCall();
}
}
if (Jumping)
{
TimeSinceJump += Time.deltaTime;
}
if (TimeSinceJump > 0.2f && DoubleJumped == false)
{
if (Input.GetKey(KeyCode.Space))
{
DoubleJumpMethodCall();
DoubleJumped = true;
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
Grounded = true;
DoubleJumped = false;
TimeSinceJump = 0;
Jumping = false;
}
}
If you wanted the character to be able to double jump after they slid off something not jumped that would be easy to implement as well. This is all in the update method besides the collider method, there is not really a massive need for an ultra professional very efficient code if you are running a 2D game - nobody is going to be struggling for frames - If the character is on the ground then everything resets to 0 or its basic state. If they are on the ground and press space make them jump, record the time after this happens. If it is more than 0.2f seconds, and they have not double jumped yet, then if they press space again then let them double jump. Make sure they cannot double jump again. Think about it logically, where should the conditions be before the jump, during, and after the character hits the ground again. Also, why are you using minus delta time when the character is in the air but resetting to 0 when it hits the ground? And adding if they are on the ground? you can get an infinitely high number while on the ground which gets misused by at most 5 while youre in the air just to be reset back to 0? All lines passed 35 are odd, why check if the character is on the ground by their y-velocity instead of if they are touching a ground collider? this will give you massive issues later if you character bounces whatsoever and that is up to your physics material.
doubleJump = !doubleJump; things like this are not really helping efficiency but are making it harder to see what goes on in your code, imagine trouble shooting and not seeing when its true or false, only seeing when the value is flipped.
Any tutorials you may watch normally have quite a bit of elegance in the code and a lot of times something that looks much more sloppier with less methods, more if statements etc. may look worse but a lot of times it is not really going to beat up your performance unless you are doing something drastically wrong. If you are telling it to render something, redraw colliders (happens when you move a object with a translation command instead of with rigid bodies commands) then it can be computationally expensive but otherwise just keep it simple.
Also, it should be worth mentioning, I assume you are using 2D colliders and checking if your object is grounded or not with OnCollisionStay(), OnCollisionStay() is slightly slower so to speak than OnCollisionEnter and I have had issues in the past with characters getting stuck inside of colliders because of OnCollisionStay was being used. I would use any OnCollisionStay() reliant booleans to also be set to true if OnCollisionEnter is true, it will register that the ground has been touched slightly faster.