How to Jump?

So I have very specific requirements for my jumping mechanic.

  • 2D
  • Pressure sensitive; hold button for short time, short jump, hold for longer, longer jump
  • Double jump
  • Uses a state machine, so when calling jump function, use state = State.Jump ()
  • Do this in the most efficient way

I’ve been working at this for far too long and have exhausted all things I could think of :confused: Starting to wonder if using a state machine for jumping isn’t going to work.

Any help would be greatly appreciated!

Some of the code (the problem is when I call NextState inside JumpState enum, it causes JumpState to loop, which causes infinite jumps instead of only a max of 2):

    // Start NextState
    void NextState ()
    {
        // If is visible
        if (isVisible)
        {
            string methodName = state.ToString () + "State";
            System.Reflection.MethodInfo info = GetType().GetMethod (methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            StartCoroutine ((IEnumerator)info.Invoke (this, null));
        } // End if visible
    } // End NextState  

    // Start FixedUpdate
    void FixedUpdate ()
    {
        // If is not dead
        if (state != State.Dead)
        {
            // If y velocity is less than 0 (negative)
            if (rb.velocity.y < 0)
            {
                // Fall faster than you rose
                rb.AddForce (Vector2.down * randFallNum);
            }

            // If any input
            if (Input.anyKey)
            {
                // If is grounded
                if (isGrounded)
                {
                    // If jump input
                    if (Input.GetButtonDown ("Jump"))
                    {
                        // Set state
                        state = State.Jump;
                    } // End jump input
                } // End if grounded

                // If not grounded
                if (!isGrounded)
                {
                    // If any input
                    if (Input.anyKey)
                    {
                        // If jump input and can double jump
                        if (Input.GetButtonDown ("Jump") && canDoubleJump)
                        {
                            // Set state
                            state = State.Jump;

                            // Set vars
                            canDoubleJump = false;
                        } // End if jump input
                    } // End if any input
                } // End if not grounded

            // Else if no input
            else if (!Input.anyKey)
            {
                // If grounded
                if (isGrounded)
                {
                    // Set state
                    state = State.Idle;
                } // End if grounded
            } // End if no input
        } // End of if dead
     } // End of FixedUpdate

    // Start Jump
    IEnumerator JumpState ()
    {
        yield return 0;

        // Set vars
        rb.velocity = new Vector2 (rb.velocity.x, 0);

        // If running
        if (speed == runSpeed)
        {
            // Jump
            rb.AddForce (transform.up * jumpForceRun, ForceMode2D.Impulse);
        }

        // If not running
        if (speed == walkSpeed)
        {
            // Jump
            rb.AddForce (transform.up * jumpForce, ForceMode2D.Impulse);
        }

        // Call function
        NextState ();
    } // End Jump