Triple Jump and Double Midair Dodge (plus more)

private void OnJump()
    {
        if (stateMachine.CurrentJumps < stateMachine.MaxJumps)
        {
            stateMachine.CurrentJumps++;
            stateMachine.SwitchState(new PlayerJumpingState(stateMachine));
        }
    }

void OnDodge()
{
    if(statemachine.CurrentMidAirDodges<stateMachine.MaxMidairDodges)
    {
        stateMachine.CurrentMidAirDodges++;
        stateMachine.SwitchState(new MidAirDodgeState());//I forgot what you calledit
    }
}

Finally, in any check for IsGrounded (like Tick() in PlayerFallingState(), add

stateMachine.CurrentJumps=0;
stateMachine.CurrentMidAirDodges = 0;
1 Like

Thank you so much, this helps a lot. I’m still scratching my head in figuring out why simply adding stateMachine.CurrentMidAirDodges++; would make such a difference.

One thing standing in the way from jumping perfection. If I jump from the ground, I get 4 jumps. However, if I start jumping while falling, I get the desired 3. Why could this be?

UPDATE (epic facepalm)

I forgot to add the same lines of code to my grounded Freelook and Targeting States! Everything works as intended. Thank you again for helping me with this!

Because it’s the most convenient way to increase CurrentMidAirDodges when you expose the variable publicly.

It does occur to me, though that the current solution runs rough-shod over the Law of Demeter (any time you find yourself actually manipulating a variable directly in another class, you’re brushing up against bad practices…

It might be better to toss in a couple of convenience functions in StateMachine, starting with changing CurrentJumps and CurrentMidAirDodges to private variables.

private int currentJumps=0;
private int currentMidAirDodges = 0;

public bool CanJump() => currentJumps < MaxJumps;
public bool CanMidAirDodge() => currentMidAirDodges < MaxMidairDodges;

public void SpendJump()
{
    currentJumps++;
}
public void SpendMidAirDodge()
{
    currentMidAirDodges++;
}
public void ResetJumpAndDodgeCounters()
{
   currentJumps = 0;
   currentMidAirDodges = 0;
}

Then I would change your OnJump() and OnDodge() methods accordingly:

private void OnJump()
{
   if(stateMachine.CanJump())
   {
        stateMachine.SpendJump();
        stateMachine.SwitchState(new PlayerJumpingState(stateMachine);
   }
}

void OnDodge()
{
    if(stateMachine.CanMidAirDodge())
    {
         stateMachine.SpendMidAirDodge();
         stateMachine.SwitchState(new MidAirDodgeState(stateMachine));
   }
}

In turn, I would add to the Enter of each of the states that would be grounded

stateMachine.ResetJumpAndDodgeCounters();

Yep, it’s a bit of refactoring, but it redirects responsibility for tracking jumps and dodges back to the StateMachine where the counters are stored.

This actually gives you some flexibility in the long run. For example, you may have an enemy who can cast a debuff on the player to prevent them from jumping at all… By moving the logic back to the central StateMachine location, you don’t have to test for this in each of the locomotion states (and the jumping state). Perhaps you drank a potion that doubles your jumps or dodges? Again, you can test for these things in the StateMachine instead of needing to test them in every state. This is what the Law of Demeter is intended to do… to hid the innerworkings of “how do we know if we can jump?” from the classes that depend on it.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms