'How to handle jump animation in Unity?

My main issue is how to stop jump animation (after it triggers, it played infinetly).

This is my code:

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

public class PlayerMovementScript : MonoBehaviour
{
    [SerializeField] float runSpeed;
    [SerializeField] float jumpSpeed;

    Vector2 moveInput;
    Rigidbody2D playerRigidbody;
    Animator playerAnimator;
    CapsuleCollider2D playerCapsuleCollider;

    void Start()
    {
        playerRigidbody = GetComponent<Rigidbody2D>();
        playerAnimator = GetComponent<Animator>();
        playerCapsuleCollider = GetComponent<CapsuleCollider2D>();
        
    }
    void Update()
    {
        Run();
        FlipSprite();
    }

    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        Debug.Log(moveInput);
    }

    void OnJump(InputValue value)
    {
        if(!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }

        if(value.isPressed)
        {
            playerAnimator.SetBool("isJumping", true);
            playerRigidbody.velocity += new Vector2(0f, jumpSpeed);
        }
    }

    void Run()
    {
        Vector2 playerVelocity = new Vector2(moveInput.x * runSpeed, playerRigidbody.velocity.y);
        playerRigidbody.velocity = playerVelocity;

        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;

        playerAnimator.SetBool("isRunning", playerHasHorizontalSpeed);
    }

    void FlipSprite()
    {
        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
        if (playerHasHorizontalSpeed) {
            transform.localScale = new Vector2(Mathf.Sign(playerRigidbody.velocity.x), 1f);
        }
    }
}

Ant this is my current animator:

enter image description here

Bools: From Idle to Jump:

  • isJumping = true From Jump to Idle:
  • isJumping = false
  • isRunning = false From Jump to Run:
  • isJumping = false
  • isRunning = true From Idle to Run:
  • isJumping = false
  • isRunning = true From Run to Idle:
  • isRunning = false

I tried few attempts with isGrounded from this tutorial, but after changes my character can only jump and animation still works uncorrectly: https://www.youtube.com/watch?v=FTxQKHG5WCA

How to fix that?

#Update 1:

I tried this code bellow, but my character only can jump after changes and animation still not working:

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

public class PlayerMovementScript : MonoBehaviour
{
    [SerializeField] float runSpeed;
    [SerializeField] float jumpSpeed;

    [SerializeField] Transform groundCheckCollider;
    [SerializeField] LayerMask groundLayer;
    [SerializeField] bool isGrounded;
    const float groundCheckRadius = 0.2f;

    Vector2 moveInput;
    Rigidbody2D playerRigidbody;
    Animator playerAnimator;
    CapsuleCollider2D playerCapsuleCollider;

    void Start()
    {
        playerRigidbody = GetComponent<Rigidbody2D>();
        playerAnimator = GetComponent<Animator>();
        playerCapsuleCollider = GetComponent<CapsuleCollider2D>();
        
    }
    void Update()
    {
        Run();
        FlipSprite();
        GroundCheck();

        playerAnimator.SetFloat("yVelocity", playerRigidbody.velocity.y);
    }

    void OnJump(InputValue value)
    {
        if(!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }

        if(value.isPressed)
        {
            playerAnimator.SetBool("isJumping", true);
            playerRigidbody.velocity += new Vector2(0f, jumpSpeed);
        }
    }

    void Run()
    {
        Vector2 playerVelocity = new Vector2(moveInput.x * runSpeed, playerRigidbody.velocity.y);
        playerRigidbody.velocity = playerVelocity;

        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;

        playerAnimator.SetBool("isRunning", playerHasHorizontalSpeed);
    }

    void FlipSprite()
    {
        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
        if (playerHasHorizontalSpeed) {
            transform.localScale = new Vector2(Mathf.Sign(playerRigidbody.velocity.x), 1f);
        }
    }

    void GroundCheck()
    {
        isGrounded = false;
        Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckCollider.position, groundCheckRadius, groundLayer);
        if (colliders.Length > 0)
        {
            isGrounded = true;
        }
        playerAnimator.SetBool("isJumping", !isGrounded);
    }
}


Solution 1:[1]

This is how i handle it:

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

public class PlayerMovementScript : MonoBehaviour
{
    [SerializeField] float runSpeed;
    [SerializeField] float jumpSpeed;
    [SerializeField] float climbSpeed;

    Vector2 moveInput;
    Rigidbody2D playerRigidbody;
    Animator playerAnimator;
    CapsuleCollider2D playerCapsuleCollider;
    float gravityScaleAtStart;

    void Start()
    {
        playerRigidbody = GetComponent<Rigidbody2D>();
        playerAnimator = GetComponent<Animator>();
        playerCapsuleCollider = GetComponent<CapsuleCollider2D>();
        gravityScaleAtStart = playerRigidbody.gravityScale;

    }
    void Update()
    {
        Run();
        FlipSprite();
        ClimbLadder();
        Falling();
    }

    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        Debug.Log(moveInput);
    }

    void OnJump(InputValue value)
    {
        if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }

        if (value.isPressed)
        {
            playerRigidbody.velocity += new Vector2(0f, jumpSpeed);
        }
    }

    void Run()
    {
        Vector2 runVelocity = new Vector2(moveInput.x * runSpeed, playerRigidbody.velocity.y);
        playerRigidbody.velocity = runVelocity;

        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;

        if (playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground")))
        {
            playerAnimator.SetBool("isRunning", playerHasHorizontalSpeed);
        } else
        {
            playerAnimator.SetBool("isRunning", false);
        }
    }

    void FlipSprite()
    {
        bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
        if (playerHasHorizontalSpeed)
        {
            transform.localScale = new Vector2(Mathf.Sign(playerRigidbody.velocity.x), 1f);
        }
    }

    void ClimbLadder()
    {
        if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))) {
            playerRigidbody.gravityScale = gravityScaleAtStart;
            playerAnimator.SetBool("isClimbing", false);
            playerAnimator.SetBool("isClimbingIdle", false);
            return;
        }

        Vector2 climbVelocity = new Vector2(playerRigidbody.velocity.x, moveInput.y * climbSpeed);
        playerRigidbody.velocity = climbVelocity;
        playerRigidbody.gravityScale = 0;

        bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
        playerAnimator.SetBool("isClimbing", playerHasVerticalSpeed);
        playerAnimator.SetBool("isClimbingIdle", !playerHasVerticalSpeed);
    }

    void Falling()
    {
        if (
            playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))
            || playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))
        ) {
            playerAnimator.SetBool("isJumping", false);
            playerAnimator.SetBool("isLanding", false);
            return;
        }

        bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
        if (playerRigidbody.velocity.y >= 0)
        {
            playerAnimator.SetBool("isJumping", playerHasVerticalSpeed);
            playerAnimator.SetBool("isLanding", false);
        } else
        {
            playerAnimator.SetBool("isJumping", false);
            playerAnimator.SetBool("isLanding", playerHasVerticalSpeed); 
        }   
    }
}

And animator:

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yardi