#anyone know of good ways to improve enum based player state code?

1 messages · Page 1 of 1 (latest)

mild crater
#

I figured "oh i should use an enum instead of a scattered collection of 100 booleans" which is probably true but i ended up just doing what i did with the booleans and end up with anomalies like

if (IsGrounded() && rb.linearVelocity.magnitude > 0.01f && (pc.plrState == playerState.IDLE || pc.plrState == playerState.IN_AIR) && pc.plrState != playerState.IN_CANNON) {
    pc.plrState = playerState.WALKING;
}

This is TERRIBLE code (and i think you will agree)
-# a quick explanation on each: isgrounded (is grounded), checking if they're moving with velocity, checking if they're idle or in the air is because I need it to switch, also for SOME reason if I fall to the ground it wont let me sprint, even though im in the walking state (print statement can confirm) unless this check is here. And lastly in cannon because if the player is on the ground and try to enter the cannon it just switches back to my grounded code and breaks physics (but that's a sepeerate problem that I do have plans to fix later)

(for context this is my enum)

public enum playerState {
    IDLE,
    WALKING,
    SPRINTING,
    GLIDING,
    IN_AIR,
    IN_CANNON
}

it has led to some improvement in the readibility and maintainability of my code, big plusses in that department.

Does anyone have any just ideas of how I could potentially improve this system? I want to make good scalable code as I add features into the game but it's really weird right now and I dont want to have 1 billion &&s and ||s in a single if else statement. This might also lead to the same unpredictability and bugginess that can come from the booleans that I wanted to avoid.

undone yarrow
#

pc.plrState != playerState.IN_CANNON
you just don't need this part

#

you've already checked that the state is something else

#

a few ideas:

  • you could have properties that check for multiple states, if they're used together often.
  • you could consider merging some states - are IDLE, WALKING, and SPRINTING really that different? maybe IN_AIR as well
  • for the main handling in Update or whatever, i tend to use a switch and separate out the behavior of each state. with that, you can let each state define what states it can transition to, or merge behavior with other states using goto
#

i don't know the specifics of your game, so this might be inaccurate, but i'd separate by specific, mutually-exclusive action
maybe just, Idle, Gliding, InCannon there

Idle && !IsGrounded() would be the same as InAir as you have now

#

player states don't have to map 1:1 with animation states, in fact they probably shouldn't

lyric cargo
#
public enum PlayerState 
{
    GROUNDED,
    AIRBORNE,
    OCCUPYING,
}

public enum GroundedState
{
    IDLE,
    WALKING,
    SPRINTING,
}

public enum AirborneState
{
    IDLE, //Airborne with no input
    SOARING, //Represents moving in the air but not exactly using a flying ability
    FLYING, //Airborne using a flying input
}

public enum OccupiedState
{
    IN_CANNON,
    IN_VEHICLE,
}```
Some ideas for substates when you need more than a flag
mild crater
#

interesting

lyric cargo
#

But as you can see there's a minor problem with splitting it out here and that's with having IDLE in two of these substates

mild crater
#

I used seperation of idle walking and sprinting for when I animate the player later but maybe I’ll have an enum just for player actions and one for the animation stages

#

That could work

#

but I’d imagine there’s still some difference that’s important

#

like speed controlling and whatnot since sprinting is a flag not an action from holding down the key

#

I had to include the cannon part because of how that code works yes I will be removing it in future

#

it did make a difference for some reason

#

I get what you mean though

lyric cargo
#

Or if your animations are strictly tied to input you can use a similar idea but check input of those current frames when you're in that neutral state

#

usually you design your states around what input is available, but for smaller projects I am guilty of having similar backend states to my animation states

undone yarrow
#

if your animation already uses, for example, velocity parameters, your code doesn't really need to account for that at all

#

just set the general player state and the velocity, and let the animator handle it

#

consider how the output behavior differs when splitting out player states

#

are there actions you can do while walking that you can't do while sprinting, and vice versa? if not, it probably makes more sense for them to be the same state