Lessons learned: Text

Hopefully this becomes a series of Lessons Learned. This is the first lesson is how we improved in-game text loading.

In-game text was originally baked-in to the code using an automated (sort of) process. The process went something like this:

  1. Update an XML resource file (these were .resx resource files) with the new text
  2. Run a custom tool to output a .cpp and .h file that had literals of the strings
  3. Rebuild the code

That’s only three steps, and the nice thing is that now you can refer to any game string using a constant identifier that’s automatically generated for you. In other words, to refer to a string, you just have to do this:

GameStrings is just a pointer to a much larger static array with all strings in every language. When you change languages in-game you just change where that pointer points.

There’s a big problem with this. It still takes too much time.

Content creation is very iterative. You create the content, import it into the game, see how it looks, change it, reimport it, on and on. So even though it’s just a three step process to import text into the game, it doesn’t take long at all before all that time adds up.

The solution we found was to just store each string in a UTF8 encoded file (each language still has its own file), and then manually create the identifier constants. So the process for adding a string looks like this:

  1. Update GameStrings.h to add an enum value
  2. Update strings-en.txt (for English; other languages are the similar) with the new string

Modifying a string is just updating strings-en.txt and issuing a refresh command to the game. No need to rebuild the game! Updating in-game text just went from a 3 minute process to a 30 second process. And that really adds up.

It seems so obvious now. Moral: make sure your “automated” process is actually better than the manual process.