Best way to store fixed game configuration data

I’m a bit puzzled as to the best and most reliable way to store some configuration data for my game. The characteristics of this data are:

  • The data is never visible to the player, it is purely back-end to control the creation of certain assets
  • The data types are numerous, i.e. bools, floats, strings etc
  • The data is constant and does not change

Essentially I have an array of 40 planets that I need to create throughout my game, and each planet has its own unique set of data which I need to access periodically throughout the game, as it plays a role in the creation and appearance of the planets.

There are so many ways to to do this so I am not sure which is best, right now I have just dumped everything into a static class and retrieving it via a dictionary:

public static class PlanetMaterialConfigs
{
    // Dictionary to return the correct data config pack by material name
    public static Dictionary<string, PlanetMaterialData> allConfigs = new Dictionary<string, PlanetMaterialData>()
    {
        ["Frozen 1C"] = Config_1
        // Same for remaining 39 configs

    };
 
    // Configuration data for each material
    public static PlanetMaterialData Config_1 = new PlanetMaterialData
    {
        name = "Frozen 1C",
        rotationSpeed = Random.Range(6, 12),

        terrain = PlanetMaterialData.TerrainType.solid,
        waterSpeed = -1,

        effect = PlanetMaterialData.EffectType.cloud,
        effectTilingXoffset = true,
        effectTilingYoffset = false,

        pulseEffect = false,
        effectStrength = 0.25f,
        effectSpeed = 0.33f,
        effectPulseTime = -1
    };

    // .. repeat for 39 more configs

}

I can’t help but feel this is a very poor way of handling this data. Can someone please recommend the best way to go about this? I really want the data itself to be stored, i.e. I do not want to create a bunch of prefab game objects that already have the correct materials applied, that’s a completely different subject and not the point of my question.

Perhaps I should be using some sort of JSON file?

Sounds like a job for ScriptableObjects assets.
Their advantages:

  • You can view them in the inspector.
  • You can manipulate them at runtime (editor only) yet they are immutable assets in builds.
  • Adding custom ui for testing/debugging is easy (Unity Inspector).
  • They support any datatype the unity serializer knows.
  • No need for any custom load or deserialize code.
4 Likes

Thanks geo immutable in builds sounds very promising! I need the data to be fixed in a very reliable way. I shall certainly look into this in more detail.

2 Likes

Exactly this.

By the way guys… if I configure a material in the Editor and I store it as an asset in my project directory, can I trust that this material and all of its parameters will be saved forever?

I have some custom materials built with custom shaders, and I have configured all of the data in the material instances. These are saved in a project folder. Do I need to verify that these parameters are correct during my game initialisation? I would think not, since I assume Unity keeps the data safe during build. But I am not sure if I should perform this verification.

What do you guys think? I do not want to complicate things unnecessarily. Please note that the parameters I am talking about here are different to the ones above.

As with many things in programming there is no single approach which is always better than others. It largely depends on your personal preferences, and details that you can evaluate based on experience and often hard to estimate ahead of time for people not making the project.

I can only list couple of factors that I use for preferring each method in different situations. Even if you later find out the chosen approach isn’t best it’s possible to switch from one approach to others with little changes in code that consumes those configuration objects.

  • Static array/structure defined in code. I sometimes use this for very small lists (5-10 items) which I expect to rarely change during development . Often within the same source file which is going to use them. Sometimes the stuff is so simple that extra work to setup other approaches doesn’t seem worth the effort. It’s also easier to reference constants and types from other parts of code or use simple expressions for calculating the values.
  • Scriptable objects. As mentioned by geo has the benefits of easier visual editing and tweaking while playing. Makes creating and changing them more accessible to game designers and artists in the team. You can directly reference prefabs or sprites. You can often move around or rename assets referenced by scriptable objects without breaking those references in scriptable objects. Scriptable objects are also nice for properties like colors or curves which are hard to describe and tweak in text or code. If you already have a bunch of scriptable objects created and later find the need to rename some fields or replace them with more complex structures, scriptable objects are more difficult to deal with. You can in theory create an editor script which would migrate your existing scriptable objects to the new structure, but it’s often more work than doing simple search and replace with other aproaches.
  • Text file with serialized data in format of your choice (json, xml, plenty of other serialization formats). In many aspects stand between static arrays and scriptable objects. Less accessible to non coders than scriptable objects with editor GUI but better than stuff defined in code. Referencing prefabs and sprites is more difficult in text files, and its easier to break stuff when you rename or move those assets. In some cases where you have to deal with lot of items somewhere between 50 and few hundreds I find text files easier to deal with than switch between folder full of scriptable objects or scrolling through long list in inspector. With text files you can more easily do stuff like search and replace using text editor of your choice. It’s also easier to generate text files with serialized data using external tools or programs. If you are considering to have mod support, text files with serialized data are both easier to setup for you and also much easier to create and edit for modders compared to scriptable objects. It’s easier to deal with recursive data structures in custom serialized text files than with scriptable objects.
1 Like

Thanks for the detailed explanation! I think when taking your advice into account, Scriptable Objects seem like the best fit. I have already started implementing them and I am finding them very well suited to this purpose, it is extremely easy to set the data and make use of it in a script!

I would be interested to hear your thoughts on my previous question (post #5)?

No one does that. Materials aren’t much different from any other unity assets. And if you can’t trust them, you shouldn’t use 90% of other unity features like scenes, prefabs, animations and sprites. How would you even know whether they are correct or not. By storing that in different structure? In that case why have the material assets at all, why not use the data from whatever you are using to compare it against? As for accidental changes during development you should be using version control.

There are some cases where you might check all the game files using checksums and digital signatures. But then you are going into DRM and anticheat territory. Which in many cases is waste of everyone time and resources. Basic check that download didn’t get accidentally corrupted should already be handled by Steam or whatever store you use to distribute your game.

2 Likes

Thanks Karliss, yes you make perfect sense and it supports what I was already thinking. It’s just that I have put in a lot of effort to configure my materials and the thought of them being lost during the build process makes me a bit paranoid, but you’re right that the same logic applies to all other assets too. So I will avoid letting my paranoia get the best of me!

Really appreciate your insights.

Everything you are dealing with is SOFTWARE. This means it is SOFT and can change.

You really really really want to STOP wasting your brain on silly worry stuff like this. This is the year 2022, we have evolved excellent ways of controlling large amounts of data over the duration of a project’s development.

Broadly this is called source control.

Please consider using proper industrial-grade enterprise-qualified source control in order to guard and protect your hard-earned work.

Personally I use git (completely outside of Unity) because it is free and there are tons of tutorials out there to help you set it up as well as free places to host your repo (BitBucket, Github, Gitlab, etc.).

You can also push git repositories to other drives: thumb drives, USB drives, network drives, etc., effectively putting a complete copy of the repository there.

As far as configuring Unity to play nice with git, keep this in mind:

Here’s how I use git in one of my games, Jetpack Kurt:

Using fine-grained source control as you work to refine your engineering:

Share/Sharing source code between projects:

Setting up an appropriate .gitignore file for Unity3D:

Generally setting Unity up (includes above .gitignore concepts):

It is only simple economics that you must expend as much effort into backing it up as you feel the work is worth in the first place. Digital storage is so unbelievably cheap today that you can buy gigabytes of flash drive storage for about the price of a cup of coffee. It’s simply ridiculous not to back up.

“Use source control or you will be really sad sooner or later.” - StarManta on the Unity3D forum boards

Thanks Kurt, you’re absolutely right so I appreciate your advice. I think perhaps I didn’t phrase myself very well though. I’m not concerned about losing my data in a general sense, I always back-up and keep versions for that.

What I meant was, if I store a material within a project folder that has a lot of custom data in it, e.g. manually set float values etc., can I trust that Unity will keep that data in that material when I build and deploy my game. The answer is yes so in that sense I think I was fussing over nothing.

But I take your point very seriously regarding proper version control.

This is common in programming, try to stop doing it and get some work done. IF it becomes a problem then worry about it.

1 Like