Efficiency of Scriptable Object as String Resources vs other string reference lookups

I was always taught that hard-coded strings were not desirable and to remove them wherever possible.

A few years ago I made my first android app, which utilized a XML document for global string resources. I don’t exactly know the technical details as to why this was used/preferred - it was my first app - but I do recall that it was very useful for creating global references to colors, strings, etc.

I was considering doing something similar as a ScriptableObject, and was wondering if this was efficient or if there was a generally more accepted Unity way of accomplishing this. I’m not very knowledgeable about which types of calls are more efficient than others (recently learned about using sqrMagnitude vs magnitude, for example)

My thought for a potential implementation would be something like:

using UnityEngine;

public class StringResource: ScriptableObject
{
    public string exampleVariable = "PlayerName"
    public string anotherExampleVariable = "GameName";
    public string exampleURLOutlink = "https://forum.unity.com/forums";
}

and then simply calling it in code elsewhere such as:

using UnityEngine;

public class OpenLink : MonoBehavior
{
    public StringResource stringResources;

    public void OpenResourceURL()
    {
        Application.OpenURL(stringResources.exampleURLOutlink );
    }
}

I suppose another way of doing this would be through a static class as well? Any suggestions?

It depends on:
A) Where you want these values to be set.
B) How often they’ll need to change.

Using a ScriptableObject, XML / Json / CSV file is the “configuration” approach, which is to say that it’s data that you write externally to the code, import/load, and then use to affect the way that the program operates. That’s perfectly valid, depending on the kinds of data you’re using. However, it adds complexity to the system in that tracking down a given configuration value is more difficult than just “Go to definition” in the IDE.

The only real difference between a ScriptableObject (YAML) and any other text file type is that SOs automatically have an inspector for serialized fields, so that you can edit it without needing to serialize and deserialize the data manually. This is a real benefit if your entire workflow is in Unity, as it cuts out a lot of plumbing, but it makes it annoying if you want to be able to edit or generate those configuration files externally.

Alternatively, you can use a static class, and usually when you do this, you set the values as constants. A constant is not the same as a configuration value in the strictest sense, because when the assembly is compiled, all instances where the constant is references is replaced with its literal value. That means anywhere “exampleURLOutline” is referenced in your example, it literally replaces that with the value you’ve set, and the field itself effectively ceases to exist in the compiled code.

This is a pretty big deal for a few reasons: it has zero overhead when used that way, because there are no lookups or references (not even a field access at the memory level), there’s no added complexity dealing with serializing and deserializing the data in the files, and it’s trivial to check the value in the IDE at any time.

Entirely up to you which you use- there aren’t really any cases where one approach is viable and another isn’t, just how easy/difficult it is for you to set up and use in your specific dev project.

1 Like

Yes, globals (static vars in C#) are very simple to use. Using a class instance is a little slower and a tad more complicated (as Lysander alludes), but allows multiple copies. Suppose your colors and messages change for levels 11-15, then again for 16+. Simply create two more instances of that scriptableObject class and swap as needed.

Of course, you can do the same thing using real globals. Write a function like “setupGlobals(int levelNum)” to manually set each variable (which could be from XML, or any other way). That will only stop working when you need multiple “globals” at the same time – red orcs have one set, blue goblins another. But that’s getting pretty far.

1 Like

Thanks for the well-written answer. This in particular was very interesting to learn!