Lua integration into a game

Started by
12 comments, last by Key_46 11 years, 7 months ago
I'm programming a game in C++, and I've decided to integrate Lua into it to separate several parts of the game. Currently my ideas of implementing it is to create a ScriptManager singleton class to handle all scripts in the game. This singleton will maintain a single Lua state which will be shared across every game object that are exposed to Lua. Then any calls to scripts will refer to this ScriptManager class and call something like ScriptManager::DoScript("script.lua");

[font=arial,helvetica,sans-serif]How do you guys manage scripts in your game?[/font]
Advertisement
You're going to catch some flak for using a singleton, even if the use is justified. Thread safety should be a concern of yours, if you are using multiple threads. Otherwise, all I have to say is it sounds fine, but be aware that you generally only have to luaL_dofile(---) once, and then use C++ functions that interface directly with your virtual machine (so instead of ScriptManager::DoScript("filename.lua") I would suggest ScriptManager::some_function(some_args), where some_function pushes the Lua function name and arguments onto the VM's stack then calls said function. Remember, when you're executing a .lua, it defaults to the global namespace, and you dont generally want to access your scripts that way, except to initialize them.

But, others might know better. This is just how I use lua, and I dont run into trouble with it.
So assuming I use the singleton implementation, I will have to set up a loop to call luaL_dofile for each of the scripts I will use in my game, and from there when I want to call a function in Lua, I will use the ScriptManager and manipulate the stack to call the Lua function?
If I were in your shoes I would make a scripts folder, then load every script in the folder during runtime and put through luaL_dofile. This way the end user could add any number of extensions or addons as they wish. Create a special C++/Lua api, where you register certain C functions inside lua. These functions when called will act as hooks to common game tasks/functions. These scripts will allow any number of modifications to the game runtime. Once all scripts have been run execute the game with all changes in effect. The scripts should be made optional and not required to run a basic game. For example an optional script could add another level, or new kinds of weapons.
I don't even go that far. I only run luaL_dofile on a .lua which calls a hooked C++ function that itself calls luaL_dofile on the argument passed. Thus, I never have to recompile the project when I add a new script, or when a script wants to import another script file (loading every file in the scripts folder adds extra hoops for seperating one mod from another). In other words, the engine only looks for init.lua, and init.lua is just a series of "DoScript("file.lua")". By doing this, a mod manager can easily append or delete the varius DoScript("file.lua") lines and your mod is loaded painlessly.

Otherwise, I handle things exactly as you and kd7tck said.
Thanks guys for the kind replies and suggestions. Another question, say I want to use Lua to configure my game GUIs. Do I expose the various GUI elements' member functions such as [font=courier new,courier,monospace]setPosition(x, y)[/font] to Lua, and then in the GUI's [font=courier new,courier,monospace]init[/font] method I run the Lua function that handles the positioning of these GUI controls? Or would it be a better approach to make the GUI's class (for example the MainMenu class) exposed to Lua and do everything in Lua instead?

(Is there an edit post option here?)

Just to be clear, currently all of my game states are implemented as different classes (MainMenu, Options, etc.), and each of them has an init() method which is called when they are switched into the game.


I don't even go that far. I only run luaL_dofile on a .lua which calls a hooked C++ function that itself calls luaL_dofile on the argument passed. Thus, I never have to recompile the project when I add a new script, or when a script wants to import another script file (loading every file in the scripts folder adds extra hoops for seperating one mod from another). In other words, the engine only looks for init.lua, and init.lua is just a series of "DoScript("file.lua")". By doing this, a mod manager can easily append or delete the varius DoScript("file.lua") lines and your mod is loaded painlessly.

Otherwise, I handle things exactly as you and kd7tck said.


Why would I recompile after adding a script?

Simply program main() to search for all files in the scripts folder and load each one in. No need to pass every file name in through a lua file. This makes things easier for end users; if all an end user has to do is drop in a file then that is ideal.

Thanks guys for the kind replies and suggestions. Another question, say I want to use Lua to configure my game GUIs. Do I expose the various GUI elements' member functions such as [font=courier new,courier,monospace]setPosition(x, y)[/font] to Lua, and then in the GUI's [font=courier new,courier,monospace]init[/font] method I run the Lua function that handles the positioning of these GUI controls? Or would it be a better approach to make the GUI's class (for example the MainMenu class) exposed to Lua and do everything in Lua instead?


That will depend on how much control you want to give to the end user. Do not do everything in lua, the game loop needs to be in C++ not lua. You could have a hook that generates a custom state dynamically and places it onto a global state machine.
A somewhat different perspective here. I use lua in my RPG, for scripting things like quests, conversations, etc. Every time I run a lua script, I actually create a whole new lua instance (by calling luaL_newstate(), luaL_openlibs(), luaL_loadstring(), and lua_pcall()). I implemented things this way at first because it was easy, with the intention that if performance was an issue, I could always go back and optimize.

To my pleasant surprise, the performance has been excellent, and no need to chance anything. I should note that I call scripts relatively rarely (a script won't be called every time through the game loop), and my scripts tend to be quite small and self-contained.

Hope that helps,
Geoff

This topic is closed to new replies.

Advertisement