Loca breaks with no internet?

I have set preload behavior to “no preload” in the settings but as soon as I start the game without anything downloaded previously with Internet turned off the log gets spammed with errors that it can not load loca bundles and that the locale is null. The scene does not even have any loca or text at all and still it wants to load it by force.

It gets even worse once the error with the null locale appeared the game remains broken even if the Internet returns. Only a restart with internet turned on fixes it.

I tried setting the addressables group schema retry count to -1 as suggested in the tooltip to prevent downloading but it does not allow me to do it, it resets to 0. Also there seems to be no function to reinitialize localization.

What I want to achieve is: don’t load anything by default and only if there is text in the scene or I call get loca myself it should download. Is there a way to do this?

The system will need to load the locales at the start In order to know what languages are supported and to pick the initial language.
Are your addressables being hosted remotely?
Can you have a local version of the locales bundle?

Yes they are purely remote, no local bundles. Besides we don’t want local bundles I also don’t know how to have 2 versions in parallel. The loca bundle has always the entire loca in it so putting this to local + updatable is no option.

Is there no way to prevent the loca system to permanently crash without Internet in startup? It could be so easy if it works like normal addressables which can be either downloaded manually on demand or get pulled automatically when a component requests it.
My suggestion would be if preload is set to No preload it does nothing, then add a function to manually initialize loca which returns a handle which contains errors when for example the connection is dead so the client can retry by recalling that function. Or is there another trick I can try?

There are a few things you could try.

You could ignore the initial errors and reset the system when you want to retry by releasing the initialization operation.

Addressables.Release(Localization.InitializationOperation);
// Restart initialization
Localization.InitializationOperation;
  1. You could provide a custom locale provider. Create a new class that inherits from ILocalesProvider. In the Editor, assign it to LocalizationSettings.AvailableLocales and set the settings dirty so it saves. EditorUtility.SetDirty(LocalizationSettings.Instance). You will then need to return the locales, they could be loaded from addressables or just created locally in memory.

You could provide a local copy of the remote assets to fall back to. This can be done by adding them to a directory which you add to the cache with Caching.AddCache
You need to make sure the files have the correct naming and manifest, I can walk you through it if it’s something you want to try.

I tried the first suggestion and it did not work. First of all Localization namespace did not contain the handle so i used LocalizationSettings.InitializationOperation instead. Then awaiting the operation task always returns with status succeeded and no operationException but the errors are logged. Anyway i cought them with the ResourceManager.ExceptionHandler to set a flag that something went wrong. And then i called Addressables.Release(LocalizationSettings.InitializationOperation) and awaited the InitializationOperation again but no more errors are thrown as if nothing gets executed anymore so this approach failed.

The second suggestion i don’t really know how to achieve what you described but since it still has to return locales from addressables it will fail as well and a locale created in memory - how does that work and how would i assign the class inheriting from ILocalProvider in the settings?

Option 3 sounds a bit too complex for now.

But regarding a sulution (if any works) with local or memory locales, how would i still get the download error flow when trying to load a real locale from addressable without internet? I prefer option 1 though if it just would return an operationException in the handle which it doesn’t and had a retry function as you posted but also it does not work.

If you think option 1 should work i would like to see a working code snippet.

Sorry, yes it should be LocalizationSettings, not Localization.
There was 1 step I forgot, you also need to reset the LocalesProvider, however, there is a simpler way to handle this.
LocalizationSettings implements IDisposable which resets the entire system. We mainly use this for testing but it should be exactly what you need.

So do this instead:

((IDisposable)LocalizationSettings.Instance).Dispose();

// Restart initialization
Localization.InitializationOperation;
1 Like

Thanks, the disposable way worked! But the way to detect the errors is not very nice. Would it be possibble in a future update that the InitializationOperation does not return success and propagates the exception? I did not find a better way to handle the error case at the moment than this:

private bool _initializingSuccessful = true;      
       
private async void Start()
{
    ResourceManager.ExceptionHandler = CustomExceptionHandler;
    do
    {
       await InitializeLoca();
    }
    while (!_initializingSuccessful);
 
    Debug.Log("Success!");
}
private async UniTask InitializeLoca()
{
    _initializingSuccessful = true;
    var op = LocalizationSettings.InitializationOperation;
    await op.Task;
    //always returns success no matter what :(
    Debug.LogWarning($"status: {op.Status}");
    //always null :(
    Debug.LogWarning($"Exception: {op.OperationException}");
 
    //retry after 2s if failed
    if (!_initializingSuccessful)
    {
        ((IDisposable)LocalizationSettings.Instance).Dispose();
        await UniTask.Delay(TimeSpan.FromSeconds(2));
    }
}
void CustomExceptionHandler(AsyncOperationHandle handle, Exception exception)
{
    if (exception != null)
    {
        Debug.LogError(exception.Message);
        _initializingSuccessful = false;
    }
}
1 Like

I have created a bug so we can fix it in the future. https://issuetracker.unity3d.com/product/unity/issues/guid/LOC-1038

1 Like