Some time ago, in a large strategy game, I worked on the quite complex vehicle production feature. The player would research various vehicle parts of different tech level, create a blueprint for a vehicle from these parts, assign it a name and visual representation, put it into production, and then have these vehicles be deployed to units on the map.
As you can imagine, there were tons of data that defined the gameplay characteristics of all these things, their relationships (upgrade paths, allowed conversions, usage restrictions etc.), generic art/audio/names/descriptions and the same but faction-specific.
Asset organization
What I would recommend is to organize assets in such a way that everything associated with a concrete character/enemy/weapon is found in one place, rather than having one directory with all the sprite pngs, one with all localization strings, one with balance values etc. In the above project, the assets and data were spread across many locations, which made it difficult to notice when one piece was missing or out-of-date. It also made it easy to make a mistake when adding or changing a vehicle.
If it’s easier to read assets when they are organized differently, I would consider creating a script that copies the raw assets into a read-optimized structure before building the game.
Lua tables as data format
I imagine that unless you have tons of data, writing data as Lua tables is a good choice; the code auto-complete can be quite helpful. You can generate Lua files with the “kind” tables seen in your screenshots based on your asset files and folders. However, if you intend to live-update your game, I suppose you will have to send the data as e.g. json, and at that point maybe it’s easier to just have everything in the same data format.
If you want to optimize for size and load-time, someone wrote a thread on here comparing json and Lua. If you want to go hog wild, check out flatbuffers, where you define a schema for your data, write and compile your data to binary using the schema, and then generate code for reading the binary data. It sounds more complicated than it is. The tools support generating both C++ and Lua, and I’ve used it successfully in Defold.
Asset linking
I like to have the file and folder structure determine which sprite and whatnot is used for what. E.g. if I add a frost_giant
enemy to the game, I create a folder of the same name, add a definition.lua to contain the values of the enemy type, and add assets like a portrait.png and idle.ogg. If I later want to add a evolved_frost_giant
type and reuse some of the definition and assets, I define it as inheriting from frost_giant
so that assets will be grabbed from the original type.
Still, I haven’t worked out what I think is best to do with assets that are shared by many different entities and in many different contexts. What I’m saying is, the above doesn’t always work well.
Code generation
In the Defold project I’m currently working on, I generate Lua code for use in the game with custom Lua scripts external to Defold. This is useful in my case as I can define various entities concisely and then generate helper functions and tables based on these that work well with auto-complete in vscode. This also makes it much less time-consuming and error-prone when I refactor entities, as I only need to change the definition and then run the code generator script.
Faulty data checks
I would consider if it’s worth defining the expected fields of e.g. an enemy type definition, and the data type and valid value range for each field. If you have lots and lots of data this can be helpful as both documentation and a way to verify data after bigger changes.
From my experience, there are lots of issues that this type of value checks won’t find. As a result, I would also consider implementing an assets inspector in the game, where you can see e.g. all the enemies in the game, spaced out in a grid, and have UI to trigger all their animations etc. This is useful to see that they are loaded correctly and the asset linking works.