I want to be able to (only) define game states using Lua script, but I'm not sure how I should do it. Here's what I have in mind currently:

For each state, I will create a .lua file that contains a class (table) that has the same name as the file name. Each table must have a set of event handlers: onEnter (called when the state is entered), onUpdate (called every frame) and onExit (called when exiting the state). So if I want to have a MainMenuState, I will have a file called "MainMenuState.lua" which will contain something like this:

MainMenuState = {}

MainMenuState["onEnter"] = function()

MainMenuState["onUpdate"] = function(elapsedTime)

MainMenuState["onExit"] = function()

Defined states will be exposed to the game engine via a singleton StateManager class. StateManager will have a function that registers a state under a unique name:

void registerState(string stateName, string fileName);

State registration will be done in script by placing the registration codes inside an init script that is called once after the game engine is initialized:

--Register all the states needed by the game
StateManager:registerState("SplashScreen", "SplashScreen.lua")
StateManager:registerState("MainMenuState", "MainMenuState.lua")
StateManager:registerState("InGameState", "InGameState.lua")
-- etc etc

StateManager will also keep track of which state is currently active and also handle state transitions:

void changeState(string state);

  • 3
    \$\begingroup\$ may ask what is your problem? every thing looks just fine. I can only add OnRender event to your state system to make it more complete. \$\endgroup\$
    – Ali1S232
    Sep 17, 2011 at 12:38
  • \$\begingroup\$ There's no problem (yet). This is my first time using scripting for a project, and I'm just wondering if my hypothetical approach is good enough. \$\endgroup\$
    – Fishcake
    Sep 18, 2011 at 10:46

2 Answers 2


It's not entirely clear what you're asking, but there's nothing inherently "wrong" with the way you are structuring your state machine. As long as it fits the task at hand, any implementation can be considered "correct".

One change I would suggest making is to allow the states themselves to be instanced, so that you can store state in your instance. This can be as simple as:

SplashScreen = {}
local instance = setmetatable({}, SplashScreen)

SplashScreen.createInstance = function(...)
    local instance = setmetatable({}, SplashScreen)
    instance.endTime = 5.0 -- set instance data
    return instance

function SplashScreen:update(elapsedTime)
    if elapsedTime > self.endTime then -- use instance data

Note that, due to the setmetatable call, instance tracks all of your state's functions; so your 'current state' is really just an instance ref in your StateManager:

function StateManager:changeState(stateName, ...)
    local stateTable = --[[ get state from file ]]
    local instance = stateTable.createInstance(...)

    self.currentState = instance

function StateManager:call(funcName, ...)
    local fn = self.currentState[funcName]
    fn(self.currentState, ...)

I preferred to use numbers with my state systems. It's not the best way but it works great for me.

state = 1
while true do
    if state==1 then
       if 1=1 then
    if state==2 then
        if 2=2 then

works for me :)

  • 2
    \$\begingroup\$ This is a horrible horrible way of dealing with states, don't do it people! \$\endgroup\$
    – Derek
    Jan 10, 2012 at 7:36
  • \$\begingroup\$ Why is it 2xhorrible? \$\endgroup\$ Jan 10, 2012 at 14:39
  • 1
    \$\begingroup\$ @RichardSparrow Because you always need to know what each number means. If anyone else were to work on the code, or if you were to go back to try to fix a bug a few weeks or months after writing it, if state==1 would be a mystery \$\endgroup\$
    – yoozer8
    Feb 9, 2012 at 3:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .