My project has ScriptableObjects with LocalizedString references. Some of these LocalizedStrings are Smart, and I add arguments to them in code like this:
LocalizedString description = spell.description; // spell is a ScriptableObject
description.Add("damage", new IntVariable { Value = context.damage });
_display.StringReference = description; // _display is a LocalizeStringEvent component
Sometimes, after playing the game for a bit, I find that these arguments are actually being serialized into the ScriptableObject .asset files as well. This makes me feel like I might be doing something wrong here. Should I be adding arguments in a different way, or duplicating the reference before adding them or something? Or is this a bug?
Ah yes I can see how this would happen. The persistent variables are serialized so if the scriptable object gets dirty then it will be saved. Can you file a bug report? Maybe there’s something we can do.
Great, thanks! Just filed the bug report, case ID IN-8178.
In the meantime, is there a way you’d recommend changing our code to avoid this issue? Or should we just keep doing it this way and wait for a new package version?
There’s no simple way to fix this. It’s a common issue people sometimes have with scriptable objects. One thing you could do is create a copy of the object at runtime in editor and then make changes to that.
Just a side note for anyone else running into this: I’m currently fixing this by cloning any Smart LocalizedStrings that live in a ScriptableObject, like so:
class Spell : ScriptableObject
{
[SerializeField] LocalizedString _description;
public LocalizedString GetDescription() => new LocalizedString(_description.TableReference, _description.TableEntryReference);
}
// ...elsewhere, in some other class's method...
LocalizedString description = spell.GetDescription();
description.Add("damage", new IntVariable { Value = context.damage });
With this strategy, arguments are added to the clone of the LocalizedString, so they never get serialized back into the ScriptableObject. Furthermore, I make the ScriptableObject’s LocalizedString field private, so no one who’s newer to the codebase can accidentally add arguments to it.
No need to do this for non-Smart LocalizedStrings though!