# Rigidbody velocity on y axis triggering wrong animation

I’m using an enum to trigger different animations on a 2D project, and to trigger a falling animation I’m using the velocity on the y axis. However at run time there always seems to be a small velocity on the y axis, as the falling animation is playing even though the player isn’t falling.

I’m using a method to apply a falling force for when the player is falling and a jump force dependent on how long the space key is pressed. I’m also applying acceleration and deceleration on the player characters movement.

``````private enum AnimationState { idle, running, jumping, falling }
private AnimationState state;

private void Update()
{
AppyCoyoteTime();

ApplyFlip();

ApplyGravityForces();

UpdateAnimation();
}

private void ApplyGravityForces()
{
// Applying gravity depending on if the player is falling or pressing and holding the jump key
if (rb.velocity.y < 0 && !wallJump)
{
rb.velocity += Vector2.up * Physics2D.gravity.y * (fallRate - 1) * Time.deltaTime;
}
if (rb.velocity.y > 0 && !jumpAction.IsPressed() && !wallJump)
{
rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpRate - 1) * Time.deltaTime;
}
}

private void UpdateAnimation()
{
// Triggers which animation to play
if (movementInputX.x > 0f)
{
state = AnimationState.running;
}
else if (movementInputX.x < 0f)
{
state = AnimationState.running;
}
else
state = AnimationState.idle;

if (rb.velocity.y > 0.1f)
{
state = AnimationState.jumping;
}
else if (rb.velocity.y < -0.1f)
{
state = AnimationState.falling;
}

Debug.Log(rb.velocity.y);

playerAnimation.SetInteger("state", (int)state);
}

private void CalcAccelerationAndDeceleration()
{
// Calaculates acceleration and deceleration
rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);

float force = movementInputX.x * maxSpeed * accelerationSpeed * Time.deltaTime;
if (Mathf.Abs(movementInputX.x) < 0.1f)
{
force = -rb.velocity.x * decelerationSpeed;
}

// Use different value for wall climb acceleration
if (wallGrab && wallClimbAction.IsPressed() && IsOnWall())
{
if (moveAction.IsPressed())
{
rb.velocity = new Vector2(0, movementInputY.y);
rb.velocity = Vector2.ClampMagnitude(rb.velocity, climbSpeed);
float forceUp = movementInputY.y * climbSpeed * Time.deltaTime;
}
if (!moveAction.IsPressed())
{
rb.gravityScale = 0;
rb.velocity = Vector2.zero;
}
if (jumpAction.IsPressed() && coyoteTimeCounter > 0f)
{
}
}
}
``````

Welcome to floating point!!

“Think of [floating point] as JPEG of numbers.” - orionsyndrome on the Unity3D Forums

The solution is to use a small “guardband” amount (rather than zero) that you consider “close enough to zero.”

Here’s why:

Floating (float) point imprecision:

Never test floating point (float) quantities for equality / inequality. Here’s why:

https://starmanta.gitbooks.io/unitytipsredux/content/floating-point.html

https://discussions.unity.com/t/851400/4

https://discussions.unity.com/t/843503/4

1 Like

I swapped out 0 with Mathf.Epsilon:

https://docs.unity3d.com/ScriptReference/Mathf.Epsilon.html

So the UpdateAnimation and ApplyGravityForces methods look like this:

``````private void ApplyGravityForces()
{
// Applying gravity depending on if the player is falling or pressing and holding the jump key
if (rb.velocity.y < -Mathf.Epsilon && !wallJump)
{
rb.velocity += Vector2.up * Physics2D.gravity.y * (fallRate - 1) * Time.deltaTime;
}
if (rb.velocity.y > 0 && !jumpAction.IsPressed() && !wallJump)
{
rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpRate - 1) * Time.deltaTime;
}
}

private void UpdateAnimation()
{
// Triggers which animation to play
if (movementInputX.x > 0)
{
state = AnimationState.running;
}
else if (movementInputX.x < 0)
{
state = AnimationState.running;
}
else
state = AnimationState.idle;

if (rb.velocity.y > 0)
{
state = AnimationState.jumping;
}
else if (rb.velocity.y < -Mathf.Epsilon)
{
state = AnimationState.falling;
}

Debug.Log(rb.velocity.y);

playerAnimation.SetInteger("state", (int)state);
}
``````

However I’m still getting the wrong animation being triggered.

This is the Debug.Log velocity on the y-axis even though the player character is grounded there is still a downward velocity. If the jump key is pressed the jump animation is played, then the fall animation but it doesn’t go back to idle or the running animation.

Here the player character is moving left, as it accelerates the animation changes from running to falling

Oh that’s essentially zero…

Try something like

``````if (velocity.y < -0.1f)
{
// falling
}
if (velocity.y > +0.1f)
{
// rising
}
``````

Substitute 0.1f for even 0.5f, 1.0f or 2.0f or … more

One of those will feel “good.”

Push forward, don’t get hung up on zero.

1 Like

Thanks, my bad. I have used -1.0f, and it works great.

1 Like