How to only call a function once during a GameState Enum

Hi there,

I have read that people say using a GameState enum to manage the states of your game is a handy design. Usually you would use this in combination with a switch statement inside the Update function of ur GameManager class.

What I was wondering is, If I change GameState to say ‘Pause’ and I want to call a ‘TogglePauseUI()’, I only want that called once, but because my switch statement is in update, TogglePauseUI() will be called several times over.

How does one go about handling this? Booleans? Bools seem to defeat the purpose of using Enum in the firstplace.

Sorry for no code examples, I’m currently in design phase. Here’s some small example of enum setup:

enum GameState
{
    MainMenu,
    Intro,
    Tutorial,
    GetReady,
    LevelRunning,
    LostLife,
    GameOver,
    HighScore,
    Credits
}

How do you do this in update? Just add a check to see if it’s changed to call it once.
This is a basic example, not tested.

GameState currentState = GameState.MainMenu;
GameState previousState;

void Awake()
{
previousState = currentState;
}
void Update()
{
if(currentState != previousState)
{
// do your switch-statements here to toggle PauseUI and stuff
}
previousState = currentState;
}

Also, I suggest get to coding instead of designing stuff, you want to see stuff happen or nothing will ever happen. Iterating is much better than having a design document that describes everything you want to do.

Mmkay I see how that works. I suppose anything that you want running each frame during particular a state would then have to be implemented as a coroutine… right? I can’t think of an example but surely this would be the case, because now functions in the switch statements only run once. See where I’m going with this?

I’m just doing some small UML just to prepare myself a little, then I dive into the code. I just wanted to know how people go about their GameManagers.

I appreciate the help :slight_smile:

I don’t know about convention, but here’s how I manage gameStates:

void Start()
{
   gameState = GameState.Idle;
   SetGameState( GameState.MainMenu );
}

public void SetGameState( GameState newState )
{
   // check if already in the new state
   if ( gameState == newState )
     return;
   
   // set the new gameState
   gameState = newState;
   
   // here you can call functions that only fire once on state change
   switch ( gameState )
   {
     case GameState.Idle :
       SetToIdle();
     break;
     
     case GameState.MainMenu :
       SetToMainMenu();
     break;
   }
}

void Update()
{
   // here you can call functions every update fframe
   switch ( gameState )
   {
     case GameState.Idle :
       UpdateIdle();
     break;
     
     case GameState.MainMenu :
       UpdateMainMenu();
     break;
   }
}
3 Likes

Enums and switches are one way to make a state machine. But they are still pretty amateurish. Fine if you have two or three states, but it gets messy with more.

One way is to have each state as a seperate class. Define OnStateEnter, OnStateUpdate and OnStateExit methods. Then call those from your FiniteStateMavhine class.

3 Likes

Yes, StateMachines does a better job at handling this sort of thing, I gave the simplest version of how you could do it :stuck_out_tongue:

Using enums and switches is a common way to implement state machines. It does the job, though you need to stick to a strict convention to keep your code organized and readable such that the state machine logic is apparent.

Indeed, the function implementing a state is generally called over several frames until the state machine transits to another state. However, you want to call a function only once. As @Kiwasi suggested, you could handle that during the state transitions. You can still handle that using switch and enums, a transition occurs when you assign the variable gameState, so there you could place the code you want to be called only once.

In case your are interested into alternative to State Machine, I would suggest having a look at Behaviour Tree which makes it easier to handle complex logic. I’ve made a tool based on Behaviour Tree, Panda BT. You can have more information about this tool here:

http://www.pandabehaviour.com/

With Behaviour Tree, instead of “states” your define your logic with “tasks” (which seems more straight forward to express a process). If you want to execute a piece of code only once, you could do it when the task starts or when it completes. With Panda BT, this could be done as follow:

using UnityEngine;
using Panda;

public class GameManager : MonoBehaviour
{
    [Task]
    void SomeTask()
    {
        if( Task.current.isStarting )
        {
            // Here, your code will be executing only once.
        }

        // Here your code will be executed once per frame.

        if( /* some condition */  )
        {
            Task.current.Succeed();
            // Here, your code will be executing only once as well.
        }
    }
}

I agree that coding and seeing how it runs, editing, then repeating the process can be great but I personally wouldn’t say it’s “better” in any way than having a solid design document.

Having a solid document, that’s well written, will keep you on track with what you’re doing. I’m sure we all know how easy it is to get side tracked when you just start coding without planning, you end up putting in features you hadn’t even planned on and things can get messy quickly :stuck_out_tongue:

To each their own I guess, but from my experience I’ve realized that iterating over something and making it better each iteration is much better than trying to create “perfection” from the start. And you actually get to see/do something instead of thinking about it, but yeah, some kind of general direction of where you’re heading is a necessity of course.

Which development model? Welcome into the Agile vs Waterfall discussion.

Yes exactly. I’m totally pro-agile. But we should probably leave that discussion at that and not clutter up this topic with off-topic things. It was just a suggestion. Anyone can do whatever they feel is best for their project :slight_smile:

I appreciate the answers everyone, Ill have a read into Panda, Behaviour Trees, etc. Thanks guys