0
\$\begingroup\$

I have an issue with double jump for the player my code is working but I want the second double jump animation finish(idle Animation: anim.SetBool("Jump", false)] before he touches the ground can anyone help me on that here is my code :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private Animator anim;
    private float speed = 5f;
    private Rigidbody2D myBody;
    public Transform groundCheckPosition;
    public LayerMask groundLayer;
    private bool isGrounded;
    private bool jumped;
    private float jumpPower = 5f;
    private bool doubleJump;
    void Start()
    {
        myBody = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        isGrounded = false;
        jumped = false;
        doubleJump = false;
    }
    // Update is called once per frame
    void Update()
    {
        PlayerJump();
    }
    private void FixedUpdate()
    {
        CheckIfGrounded();
        PlayerWalk();
    }
    void PlayerWalk()
    {
        float h = Input.GetAxisRaw("Horizontal");
        if (h > 0)
        {
            anim.SetInteger("Speed", (int)speed);
            ChangeDirection(1);
        }
        else if (h < 0)
        {

            anim.SetInteger("Speed", (int)speed);
            ChangeDirection(-1);
        }
        else
        {
            anim.SetInteger("Speed", 0);
        }
        myBody.velocity = new Vector2(h * speed, myBody.velocity.y);
    }
    void ChangeDirection(int direction)
    {
        var temp = transform.localScale;
        temp.x = direction * (0.8f);
        transform.localScale = temp;

    }
    void CheckIfGrounded()
    {
        if (!Physics2D.Raycast(groundCheckPosition.transform.position, Vector2.down, 0.1f, groundLayer))
        {
            isGrounded = false;
        }
        else
        {
            isGrounded = true;
            doubleJump = false;
        }
        if (isGrounded)
        {
            jumped = false;
            anim.SetBool("Jump", false);
        }
    }
    void PlayerJump()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if ((isGrounded && !jumped) || (!doubleJump && !isGrounded))
            {
                jumped = true;
                doubleJump = true;
                myBody.velocity = new Vector2(myBody.velocity.x, jumpPower);
                anim.SetBool("Jump", true);
            }
        }
    }

}//class

Edit

I have changed the code from that :

void Update()
    {
        PlayerJump();
    }
    private void FixedUpdate()
    {
        CheckIfGrounded();
        PlayerWalk();
    }

to that :

void Update()
{

}
private void FixedUpdate()
{
    CheckIfGrounded();
    PlayerJump();
    PlayerWalk();
}

I have changed it because FixedUpdate, we use it only for physics because it's not called every frame, unlike update function.

the problem is that the double jump doesn't work in this case can you explain me why?

\$\endgroup\$
  • \$\begingroup\$ When you say "before he touches the ground," when specifically do you mean? Do you want to set this bool when the player reaches a particular altitude above the ground, or after a specific time, or when the estimated time to landing is below a threshold, etc? Or does this need to be a bool you set to false at all - could you transition to the jump state with a Trigger, so that you don't need to manually reset it? \$\endgroup\$ – DMGregory Nov 17 '18 at 18:11
  • \$\begingroup\$ Hi @DMGregory, thank you for your reply, I want the second jump like the first jump. the player jumps, after then he returns to this first position, before he touches the ground in my case, the first jump is okey he jumps and he returns to idle position before the collision with the ground, but when i make second space for double jump the player stays on his jump position until he touches the ground. \$\endgroup\$ – jack john Nov 17 '18 at 19:12
  • \$\begingroup\$ for more details i have recorded a video for you sir you can view it in the google drive link drive.google.com/file/d/1IKlMBB3Xm158BzD0VpIpQ6iwxJtiWN1A/… \$\endgroup\$ – jack john Nov 17 '18 at 20:10
  • \$\begingroup\$ the project is here drive.google.com/file/d/1jLzKEjcBFSKXTjlbDf7rehZz4vKh7hdu/… \$\endgroup\$ – jack john Nov 17 '18 at 20:19
0
\$\begingroup\$

So I looked into your project and here's what the issue is:

    void CheckIfGrounded()
{
    if (!Physics2D.Raycast(groundCheckPosition.transform.position, Vector2.down, 0.1f, groundLayer))
    {
        isGrounded = false;
    }
    else
    {
        isGrounded = true;
    }
    if (isGrounded)
    {
        jumped = false;
        doubleJump = false;
        anim.SetBool("Jump", false);
    }
}

This snippet is being called every tick which means, it continuously checks whether the player is near the ground and when it is, it sets the Jump bool as false which then transistions from jump animation to idle.

Why it works for single jump?

The reason is that single jump is really short in terms of height, so as soon as you jump, by the time the jump animation finishes, you are already near the floor and the transition occurs. In double jump you are high enough that by the time the jump animation finishes, you are still far from floor, thus the transition doesn't happens.

How to fix it?

One way to fix it is by simply waiting for a few seconds when jumping and then as soon as the jump animation finishes, change the boolean so the transition happens from jump to idle. You can use Coroutines to achieve that.

Second way of fixing it is by removing the ongoing transition to jump like this:

Player Animator

and after that use Animator.Play(String StateName) just when the player jumps (Jump key is pressed). I Usually use the 2nd one but both should work.

\$\endgroup\$
  • \$\begingroup\$ thank you so mush sir for your help in the same project, i have made the methods PlayerJump and PlayerWalk in the fixedUpdate and checkifgrounded in the update , but it doesn't work i have in result only one jump can you tell me why ? void Update() { CheckIfGrounded(); } private void FixedUpdate() { PlayerJump(); PlayerWalk(); } \$\endgroup\$ – jack john Nov 18 '18 at 11:39
  • \$\begingroup\$ I can't understand what you are trying to ask here. Explain your question a little bit. \$\endgroup\$ – Hasnain NoOrani Nov 18 '18 at 12:14
  • \$\begingroup\$ I have edited my post can you check the edit section ? \$\endgroup\$ – jack john Nov 18 '18 at 12:23
  • 1
    \$\begingroup\$ You can also use a Trigger instead of a Bool in order to cause a transition exactly once, rather than recurring until you manually reset the value. \$\endgroup\$ – DMGregory Nov 18 '18 at 17:46
0
\$\begingroup\$

I tried to get an answer by myself, tell me if I'm wrong or not.

Update() function runs at each frame so the playerJump() function is faster than the checkifgrounded() function so the value of isgrounded is still true because checkifgrounded() is not executed yet so the jumped and doublejump values are always false until the next execution of checkifgrounded() method, so the player jumps twice.

In the second case When we have moving the playerjump() method to fixedUpdate, in this case, the two methods checkifgrounded() and playerJump() are executed at the same time so there is no offset the isgrounded value is false as soon as we press space, so the player jump only once.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.