OnEnable Ordering causing null references when parsing arguments

tl;dr I believe that the OnEnable of LocalizedStringEvents is firing too soon, before any other components have had a chance to register Arguments.

Hello,

I’ve just started using the package and I’m very impressed so far. I’m in the process of getting my head around things, and I think I’m encountering some ordering issues when setting Arguments on a StringReference.

I have a button which changes text dynamically between “Load Game” and “New Game” depending on whether a bool HasSaveFiles is true or false. My localization string is:

"{HasSaveFiles:Load|New} Game"
In the heirarchy, it’s a standard Button with a TextMeshPro child object

  • Button
    • Text

The Text has a LocalizedStringEvent on it that I set up using the 3 dots menu → Localize
The Button object holds a script that has a reference to that LocalizedStringEvent and does essentially the following:

    [SerializeField] private LocalizeStringEvent localizedString;

    public bool HasSaveFiles { get => hasSaveFiles; }

    private void OnEnable()
    {
        localizedString.StringReference.Arguments = new[] { this };
    }

This works perfectly. I have another example that does not.

I have another object for dealing with Save Slots. It’s doing something slightly more complicated. I want it to display “1 - Continue” or “2 - New”. It has the string of

"{SlotNumString} - {HasSaveFile:Continue|New}"
This time, the heirarchy looks like this:

  • Parent
    • Button
      • Text

The parent contains a script that does basically the same as before:

    [SerializeField] private LocalizeStringEvent localizedString;
    private bool hasSaveFile;
    public string SlotNumString { get => (slotNum + 1).ToString(); }
    public bool HasSaveFile { get => hasSaveFile; }

    private void OnEnable()
    {
        localizedString.StringReference.Arguments = new[] { this };
    }

This is the result of running that code:

FormattingException: Error parsing format string: Could not evaluate the selector "SlotNumString" at 1
{SlotNumString} - {HasSaveFile:Continue|New}
-^

Visually, the text appears correctly, as the HasSaveFile is evaluated some time after the object is enabled and I refresh the string. The error only appears on the initial attempted evaluation of the arguments - because the OnEnable of the parent hasn’t run yet.

If I add a [DefaultExecutionOrder(-1000)] to the parent class, I get no such errors.

Can I solve this ordering problem in a way that doesn’t require me to manually curate the execution order of a lot of my GameObjects?

Thanks for your time.

Hi,

LocalizeStringEvent does its initialization in OnEnable as well so without manually setting the execution order its hard to predict which script will come first.
You could assign the arguments in Awake instead as this comes before OnEnable

Alternatively you could have the LocalizeStringEvent disabled by default and then enable it when you set the Arguments. Starting disabled is probably the safest approach.

You could also go into Project Settings/Script Execution Order and add UnityEngine.Localization.Components.LocalizeStringEvent, then give it a large value so it runs later than the other scrips.

1 Like

Hey Karl,

Both of those suggestions are great ideas. I’ll see which makes most sense for my project.

Thanks for your lightning-fast response!

Edit: Didn’t know about that Script Execution Order window. Super useful!

1 Like