Search Unity

Bug Localizing custom asset (Fonts) doesnt work in build

Discussion in 'Localization Tools' started by Xesk, May 10, 2023.

  1. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    Hello,

    I was building a Localization system, and followed this thread to localize the fonts in our texts.

    I've created texts prefabs with this configuration that I'm using throughout the game:


    While it works perfectly in Editor, I'm finding some erratic behaviour in Build.

    One thing I have not yet traced is that in some instances, upon starting the game, EVERY SINGLE TEXT appears blank (or default null character). Since I know the menus, I can blindly navigate through to the language settings, and when I change the languages (thus creating a LocalizationEvent call), the text appears again.

    This happens sometimes, I couldn't find why yet. But having this issue or not in a playsession, I have traced another issue when navigating the language settings: I have to navigate through the menu twice for the fonts to be changed accordingly.

    SIMPLIFIED EXAMPLE:
    1. Imagine I have this horizontal scroll to navigate through all my different languages seen in the previous image.
    2. If my current language is English, I can navigate the menu normally and see languages change.
    3. When I get to change from Italian to Polish (first lang with a different font) I will not see nor text or fonts change.
    4. If I go back to Italian and then Polish again, I will see fonts and texts updated correctly.
    5. This will happen again each time I'm navigating to languages with fonts I have not visited yet.
    The stack trace for this error reads the following:
    Uploading Crash Report
    AssertionException: Assertion failure. Value was Null
    Expected: Value was not Null
    at UnityEngine.Assertions.Assert.Fail (System.String message, System.String userMessage) [0x00043] in <34494dee0a8743c49ad9dc4c9c1f32e6>:0
    at UnityEngine.Assertions.Assert.IsNotNull (UnityEngine.Object value, System.String message) [0x00013] in <34494dee0a8743c49ad9dc4c9c1f32e6>:0
    at UnityEngine.Assertions.Assert.IsNotNull[T] (T value, System.String message) [0x0001f] in <34494dee0a8743c49ad9dc4c9c1f32e6>:0
    at UnityEngine.Assertions.Assert.IsNotNull[T] (T value) [0x00001] in <34494dee0a8743c49ad9dc4c9c1f32e6>:0
    at UnityEngine.Localization.Tables.TableEntry.get_SharedEntry () [0x0000f] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Tables\DetailedLocalizationTable.cs:35
    at UnityEngine.Localization.GetTableEntryOperation`2[TTable,TEntry].HandleEntryOverride (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] asyncOperation, TEntry entry) [0x0006f] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Operations\GetTableEntryOperation.cs:87
    at UnityEngine.Localization.GetTableEntryOperation`2[TTable,TEntry].ExtractEntryFromTable (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] asyncOperation) [0x0005e] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Operations\GetTableEntryOperation.cs:64
    at UnityEngine.Localization.GetTableEntryOperation`2[TTable,TEntry].Execute () [0x00080] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Operations\GetTableEntryOperation.cs:50
    at UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1[TObject].InvokeExecute () [0x00001] in C:\...\Library\PackageCache\com.unity.addressables@1.19.18\Runtime\ResourceManager\AsyncOperations\AsyncOperationBase.cs:474
    at UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1[TObject].Start (UnityEngine.ResourceManagement.ResourceManager rm, UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle dependency, DelegateList`1[T] updateCallbacks) [0x000a1] in C:\...\Library\PackageCache\com.unity.addressables@1.19.18\Runtime\ResourceManager\AsyncOperations\AsyncOperationBase.cs:469
    at UnityEngine.ResourceManagement.ResourceManager.StartOperation[TObject] (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1[TObject] operation, UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle dependency) [0x00001] in C:\...\Library\PackageCache\com.unity.addressables@1.19.18\Runtime\ResourceManager\ResourceManager.cs:460
    at UnityEngine.Localization.Settings.LocalizedDatabase`2[TTable,TEntry].GetTableEntryAsync (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, UnityEngine.Localization.Settings.FallbackBehavior fallbackBehavior) [0x00041] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Settings\Database\LocalizedDatabase.cs:461
    at UnityEngine.Localization.Settings.LocalizedAssetDatabase.GetLocalizedAssetAsyncInternal[TObject] (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, UnityEngine.Localization.Settings.FallbackBehavior fallbackBehavior) [0x00001] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Settings\Database\LocalizedAssetDatabase.cs:96
    at UnityEngine.Localization.Settings.LocalizedAssetDatabase.GetLocalizedAssetAsync[TObject] (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, UnityEngine.Localization.Settings.FallbackBehavior fallbackBehavior) [0x00001] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Settings\Database\LocalizedAssetDatabase.cs:69
    at UnityEngine.Localization.LocalizedAsset`1[TObject].LoadAssetAsync () [0x0000c] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Localized Reference\LocalizedAsset.cs:197
    at UnityEngine.Localization.LocalizedAsset`1[TObject].HandleLocaleChange (UnityEngine.Localization.Locale _) [0x00018] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Localized Reference\LocalizedAsset.cs:286
    at (wrapper delegate-invoke) System.Action`1[UnityEngine.Localization.Locale].invoke_void_T(UnityEngine.Localization.Locale)
    at UnityEngine.Localization.Settings.LocalizationSettings+<InitializeAndCallSelectedLocaleChangedCoroutine>d__72.MoveNext () [0x0004b] in C:\...\Library\PackageCache\com.unity.localization@1.0.5\Runtime\Settings\LocalizationSettings.cs:406
    at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00026] in <34494dee0a8743c49ad9dc4c9c1f32e6>:0




    From which I read that when the system tries to load the locale, it returns null, so the Localization Update Corroutine fails.
    But next time, the same locale is not null? How?

    I have tried to go through this solution.
    Although I'm not familiar with Adressables, it seems that everything is correct in our projects, and rebuilding didn't seem to change anything.

    What can I do?

    Unity 2021.2.14f1
    Localization 1.0.5
    Addressables 1.19.18
     
    Last edited: May 10, 2023
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    Hi,

    Could you share the code you are using?
     
  3. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    This is the LocEvent class:
    Code (CSharp):
    1. using TMPro;
    2. using UnityEngine.Events;
    3. using UnityEngine.Localization;
    4. using UnityEngine.Localization.Components;
    5.  
    6.     [System.Serializable]
    7.     public class LocalizedFont : LocalizedAsset<TMP_FontAsset> { }
    8.  
    9.     [System.Serializable]
    10.     public class UpdateFontEvent : UnityEvent<TMP_FontAsset> { }
    11.  
    12.     public class LocalizedFontEvent : LocalizedAssetEvent<TMP_FontAsset, LocalizedFont, UpdateFontEvent>
    13.     {
    14. }
    Upon changing the option from the settings menu, we have this function callback
    Code (CSharp):
    1.  
    2. public class SettingsMenu : UIScreen
    3. {
    4.     [SerializeField] private OptionHorizontalSelector languageSelector;
    5.  
    6.       public void SetLanguage()
    7.         {
    8.             GameController.Instance.Persistance.SettingsData.Language = languageSelector.GetCurrentSelected();
    9.         }
    10. }
    That goes through the Settings class
    Code (CSharp):
    1. public class SettingsDataHandler
    2. {
    3.        // ----- SettingsData -----
    4.         [System.Serializable]
    5.         public class SettingsData
    6.         {
    7.             // Everything here is an index referencing the selected option on the menus!
    8.             // Audio
    9.             public int masterVolume = 10;
    10.             public int musicVolume = 8;
    11.             public int sfxVolume = 8;
    12.             // Gameplay
    13.             public int languageID = -1;
    14.            ...
    15.         }
    16.  
    17.         // ----- SettingsDataHandler -----
    18.         private SettingsData settingsData;
    19.  
    20.         public int Language
    21.         {
    22.             get { return settingsData.languageID; }
    23.             set
    24.             {
    25.                 settingsData.languageID = value;
    26.                 LoadLanguage(value);
    27.             }
    28.         }
    29.  
    30.         //This is the function that gets called in the end. It also gets called upon game start, when loading the stored/default language:
    31.         private void LoadLanguage(int id)
    32.         {
    33.             LocalizationSettings.InitializationOperation.WaitForCompletion();
    34.             LocalizationSettings.SelectedLocale = LocalizationSettings.AvailableLocales.Locales[id];
    35.         }
    36. }
    Edits: Sorry so much editing, tring to convey the info as best as possible!
     
    Last edited: May 10, 2023
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    Could you try updating to the latest package version 1.4.3? if it's not visible in the package manager you can edit the manifest.json file in the packages folder and set it manually.
     
  5. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    YES! That does fix the issue!

    Tried to update from Package Manager but the Update button did not appear, so updated manifest.json. I guess you are aware of that.

    HOWEVER, a new error has appeared, related to the first untracked issue. Again, the text is not appearing, now showing this log:


    OperationException : Expected to have a current operation to wait on. Can not complete.
    UnityEngine.StackTraceUtility:ExtractStackTrace ()
    UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
    UnityEngine.Logger:Log (UnityEngine.LogType,object)
    UnityEngine.Debug:LogError (object)
    UnityEngine.AddressableAssets.AddressablesImpl:LogException (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle,System.Exception) (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/AddressablesImpl.cs:219)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:set_OperationException (System.Exception) (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:348)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:Complete (UnityEngine.Localization.Settings.LocalizationSettings,bool,System.Exception,bool) (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:488)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:Complete (UnityEngine.Localization.Settings.LocalizationSettings,bool,string,bool) (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:451)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:Complete (UnityEngine.Localization.Settings.LocalizationSettings,bool,string) (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:435)
    UnityEngine.Localization.Operations.WaitForCurrentOperationAsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:InvokeWaitForCompletion () (at C:/.../Library/PackageCache/com.unity.localization@1.4.3/Runtime/Operations/WaitForCurrentOperationAsyncOperationBase.cs:40)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1<UnityEngine.Localization.Settings.LocalizationSettings>:WaitForCompletion () (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:172)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1<UnityEngine.Localization.Settings.LocalizationSettings>:WaitForCompletion () (at C:/.../Library/PackageCache/com.unity.addressables@1.20.5/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:199)
    Ugly.SettingsDataHandler:LoadLanguage (int) (at C:/.../Assets/Scripts/Game/GameStorage/SettingsDataHandler.cs:201)
    Ugly.SettingsDataHandler:LoadSettingsData (string) (at C:/.../Assets/Scripts/Game/GameStorage/SettingsDataHandler.cs:160)
    Ugly.Persistance:ResetPersistentSettingsData () (at C:/.../Assets/Scripts/Game/Persistance.cs:47)
    Ugly.GameController:OnFirstAwake () (at C:/.../Assets/Scripts/Game/GameController.cs:124)
    Ugly.GameController:Awake () (at C:/.../Assets/Scripts/Game/GameController.cs:84)


    This is triggered by the WaitForCompletion when loading the default language (pasting again the code). Happens when starting the game, trying to load the saved settings:
    Code (CSharp):
    1. private void LoadLanguage(int id)
    2.         {
    3.             LocalizationSettings.InitializationOperation.WaitForCompletion();
    4.             LocalizationSettings.SelectedLocale = LocalizationSettings.AvailableLocales.Locales[id];
    5.         }
    Is that function deprecated somehow in this new patch? Or should I try to catch an exception I dont know about here?

    Btw, thanks for the quick responses, you are even faster than me! Seeing your answers in other posts too, seems like you are doing a great job around here. Really appreciated!
     
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    Nothing is deprecated. I'm not sure what would cause this. Try enabling initialize synchronously in the localization settings. Then remove the call to WaitForCompletion. See if that fixes the issues
     
  7. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    I'm also seeing these artifacts for just a frame or two when changing language.
    I will take a look into that tomorrow, lets see if I can find something causing it...
    Sin título.png

    (magenta should be letters)
     
  8. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    That did fix both issues. Thank you.
    Curious about what am I doing wrong with the async load...
     
  9. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    I'm not sure but I suspect you were calling wait for completion on an operation that has been released. The initialize synchronously flag will call it for you at the start.
     
  10. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    Ok karl, I'm sorry I'm getting back to you.

    After doing all this, I was able to have a correct build yesterday, that is behaving as expected.
    However, now that I'm working again on the Editor, I have this issue where Reloading Script Assemblies takes forever (more than 30min last time I tried).

    In the Localizations Settings, I had this Preload option:
    upload_2023-5-11_15-56-30.png

    I have found out that disabling Domain Reloading, fixed the wait time, but I dont want to do that just because I updated a package...
    The other thing I tried is to select "No Preloading". That seems to fix it too.

    Is this an expected behaviour?
     
  11. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    This sounds like its preloading all the tables during the assembly reload. It could be a bug although it could also be by design if you have a project locale selected in the editor as this will trigger the preloading. Could you please file a bug report so we can look into it?
     
  12. Xesk

    Xesk

    Joined:
    Dec 26, 2017
    Posts:
    15
    Ok. Will try to do it when crunch time finishes x)
    No time now to reproduce the issue in a test project.
     
    karl_jones likes this.