'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:
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:
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 |


