private void StateDash()
        {
            // This design pattern simplifies working with complicated velocity
            // changes.
            //
            // The pattern splits apart the original velocity into multiple
            // pieces. Each piece is stored and manipulated individually. At
            // the end, each component piece is recombined to form the output
            // velocity.
            //
            // A typical example may combine previous velocity, current axis
            // input, and velocity from a curve.

            // Feather in the previous velocity
            dashDecayVel = Vector2.MoveTowards(dashDecayVel, Vector2.zero, dashDecayAccel * Time.fixedDeltaTime);

            // Calculate raw dash velocity
            dashTimer.Update(Time.fixedDeltaTime);
            Vector2 curveOutput = dashVel.Evaluate(dashTimer.NormalizedProgress) * dashDir;

            // Blend together for smooth output
            velocity = dashDecayVel + curveOutput;

            if (dashTimer.Done)
            {
                BeginStateRun();
            }
        }
        private void StateJump()
        {
            jumpTimer.Update(Time.fixedDeltaTime);

            if (jumpTimer.Running && input.jumpHeld)
            {
                velocity.y = jumpVel;
            }
            else
            {
                BeginStateRun();
            }

            if (input.dash.PeekThenClear())
            {
                BeginStateDash();
            }
        }