The sweng-gamedev list is all a-flutter with a debate about the merits of scripting in games.Â I wrote up a response that describes our experiences and figured I’d share it here too.
We had Lua integrated into the client and wrote much of our UI logic written in it. We struggled with bugs in our glue layer, difficulty debugging, and major spikes in our frame times whenever the garbage collector ran. Of course the glue code was terrible to begin with and we were exporting script hooks for much of the game instead of a nice clean interface, so that didn’t help. After a while we started moving away from Lua and began implementing new UI in C++. We’ve now removed all the Lua from the game.
On the gameplay side we use a rich data-drive system that lets designers define an arbitrary list of “requirements” with which they are able to test most any condition. When a trigger fires, object is used, or skill is activated, an arbitrary list of “results” is activated which is capable of modifying just about any state in the game.Â The designers also have a few ways of maintaining persistent state on the characters depending on the circumstances.Â This system is working pretty well for us and eliminates the need for any designer-written scripts.
If I ever integrate scripting into an engine again, there are several things I’ll do differently to make it go more smoothly:
- No designer scripting.Â If designers are writing scripts, You’re Doing It Wrong. Scripts are code, and need to be just as maintainable as all your other code.
- A much cleaner API layer between the C++ code and the script code.Â Exporting the whole game to Lua was just dumb.
- A built-in debugger. Printf-style debugging is so incredibly painful when you’re used to having a rich source-level debugger.
- Built-in profiling. All calls across the native/script interface should be timed and memory consumption should be strictly monitored.
- Dynamic script loading. Part was stupid glue and part was just our poor use of the scripts, but the first time around we ended up loading all the scripts when the client booted and couldn’t reload most of them. This one of the major advantages of scripting and we were missing out on it.
- Much more evaluation time. We know a bunch of things to look for the next time around including slow garbage collection, object lifecycle issues, memory corruption in the glue, testability of the scripts in isolation, etc.
On the other hand, I think writing servers in a higher-level-than-C++ language like C# or Java makes a lot of sense and would save us tons of development time. It’s the dynamically typed language with no debugger that didn’t work well for us.