- Home /
Ok, going to try to reach out on this issue one more time.
Still cannot figure out how to fix this. I want to create a simple double jump. I can get it to work partially, however the current issue is that if they player is on the ground, he can jump 2 times(As should) but if he is not on the ground, he can only jump once. So it is acting if 1 of the 2 availble jumps was already used. I have tried several different methods. But I am currently at this. The user has a groundCheck that can detect if the player is grounded. Here is the script.
using UnityEngine;
using System.Collections;
public class CharacterControl : MonoBehaviour {
public float maxSpeed = 8f;
bool facingRight = true;
Animator anim;
public bool doubleJump = false;
public int jumpCount;
public bool grounded = false;
public Transform groundCheck;
public float groundRadius = 0.2f;
public LayerMask whatIsGround;
public float jumpForce = 700f;
//Apply Initial Settings.
void Start () {
anim = GetComponent<Animator>();
jumpCount = 1;
}
void FixedUpdate ()
{
//Check for ground & update the animator.
grounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
anim.SetBool("Ground", grounded);
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
//To disable controls while jumping
//if(!grounded) {return}
//that disables following code.
//Allow user movement.
float move = Input.GetAxis("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(move));
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
//Control the User 2D Rotation to Direction.
if (move > 0 && !facingRight)
{
Flip();
}
else if (move < 0 && facingRight)
{
Flip();
}
}
void Update()
{
bool jumpIsPressed = Input.GetKeyDown(KeyCode.Space);
if (jumpIsPressed && grounded)
{
Jump();
}else if(jumpCount <= 1 && jumpIsPressed)
{
Jump();
}
if (grounded)
{
jumpCount = 1;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void Jump()
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
jumpCount++;
}
}
Answer by kacyesp · Aug 26, 2014 at 09:45 PM
Initialize jumpCount to 0 in the Start() function and re-initialize it to 0 on line 68 in the if (grounded) statement.
I tried that, just tried it again. The result is now you have 3 jumps if jumping from the ground, and only 2 if you jump while in air.
Another problem might be that the "grounded" check might return true in the next update right after a Jump() if the player doesn't move high enough from the ground in 1 Update() or if the checking circle radius is too big.
If you want the player to be able to jump twice whether he starts the first jump from the ground or from the air, then why have if (jumpIsPressed && grounded) on line 57 ? Couldn't you remove the grounded variable from the if statement ?
Answer by CliffracerX · Aug 26, 2014 at 09:58 PM
Your Jump() function needs an if statement around jumpCount++ like so:
void Jump()
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
if(!grounded)
{
jumpCount++;
}
}
This is to make so it only increases the amount of times you've jumped when you're in the air, previously jumping would always use up one of your two jumps even if you were on the ground when you jumped.
I understand that, I just added it to the script. But for some reason if I walk off the platform, then press jump 2 or more times, it still only adds 1 jump. So its like the detection of input isn't working after that first jump after i am airborne.
After editing it slightly, this is what i have. Now, when i jump on a tile it adds 1 to jumpCount, but when off a tile it adds 2 instantly when jumpIsPressed.
void Update()
{
bool jumpIsPressed = Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space);
if (jumpCount < 1 && jumpIsPressed)
{
Jump();
}
else if (!grounded && jumpCount < 2 && jumpIsPressed)
{
Jump();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void Jump()
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
jumpCount++;
}
Answer by Kiwasi · Aug 26, 2014 at 10:22 PM
Let me step through the logic as written for you. Here is the ground jump logic.
FixedUpdate runs. Grounded is set to true
Update runs. Jump is called. JumpCount increases to 2. As the user is still grounded JumpCount is reset to 1
FixedUpdate runs. User starts to move up. Grounded returns false.
Update runs. Jump is called. JumpCount increases to 2.
Update runs. User cannot call jump until it is reset by grounding.
Here is the air jump logic
FixedUpdate runs. Grounded is set to false
Update runs. Jump is called. JumpCount increases to 2.
FixedUpdate runs. User starts to move up. Grounded returns false.
Update runs. User cannot call jump until it is reset by grounding.
A far better way to code this would be to use a property to reset jumpcount every time the user becomes grounded. Pseudo code:
private bool _grounded;
public bool grounded {
get {
return _grounded;
}
set {
_grounded = value;
if(_grounded){
jumpCount = 0;
}
}
}
The code above will work with your existing script. Place it instead of line 13. Also remove line 68.
This is what I did after what you suggested.
using UnityEngine;
using System.Collections;
public class CharacterControl : $$anonymous$$onoBehaviour {
public float maxSpeed = 8f;
bool facingRight = true;
Animator anim;
public bool doubleJump = false;
public int jumpCount;
private bool _grounded;
public bool grounded
{
get
{
return _grounded;
}
set
{
_grounded = value;
if (_grounded)
{
jumpCount = 0;
}
}
}
public Transform groundCheck;
public float groundRadius = 0.2f;
public Layer$$anonymous$$ask whatIsGround;
public float jumpForce = 700f;
public bool weCan = false;
//Apply Initial Settings.
void Start () {
anim = GetComponent<Animator>();
jumpCount = 0;
}
void FixedUpdate ()
{
//Check for ground & update the animator.
grounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
anim.SetBool("Ground", grounded);
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
//To disable controls while jumping
//if(!grounded) {return}
//that disables following code.
//Allow user movement.
float move = Input.GetAxis("Horizontal");
anim.SetFloat("Speed", $$anonymous$$athf.Abs(move));
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
//Control the User 2D Rotation to Direction.
if (move > 0 && !facingRight)
{
Flip();
}
else if (move < 0 && facingRight)
{
Flip();
}
}
void Update()
{
bool jumpIsPressed = Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space);
if (jumpIsPressed && grounded)
{
Jump();
}
else if (jumpCount <= 1 && jumpIsPressed)
{
Jump();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void Jump()
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
jumpCount++;
}
}
Is that right? cause its still the exact same. 3 jumps when jumping from platform, and only 2 if jumping while airborne
Just looked through it again. Your other problem is Jump is happening in Update and Grounded is being set every FixedUpdate.
Two possible strategies to solve. You should consider doing both, but either should work by itself.
Recode your grounded properties so it only resets the jumpCount if it changes.
public bool grounded {
get {
return _grounded;
}
set {
if (value && !_grounded) {
jumpCount = 0;
}
_grounded = value;
}
}
Or move your jump functionality into FixedUpdate as follows:
private bool hasJumped = false;
// In update in place of jump
hasJumped = true;
// Anywhere in FixedUpdate
if (hasJumped){
Jump();
hasJumped = false;
}
You also can optimise your Update method. Putting updating the number of jumps into the grounded properties has removed the need to treat each jump differently.
void Update()
{
if (jumpCount < 1 && Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space))
{
Jump(); // or hasJumped = true; if you decide to go that way.
}
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Multiple jump C# Script. 0 Answers
Multiple jump C# Script. 2 Answers