Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Bug 1.2.4] Duplicate TextMeshPro assets in bundles

Discussion in 'Addressables' started by MaskedMouse, Oct 2, 2019.

  1. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,091
    Due to the nature of TextMeshPro it stores its font & material assets in a
    Resources
    folder.
    Under Addressables it is listed as Build-In Data. But when you have an asset group containing a UI prefab which contains a
    TextMeshProUGUI
    element, it will build the bundle with the TextMeshPro assets as dependency inside the bundle. So each separate UI bundle will be around 424KB but it is only a prefab (See the attached bundle with Asset Bundle Browser).

    One workaround fix is to drag drop the
    Resources
    folder into another bundle. But then it will be duplicate as Built-In data and a Bundle. But it will reduce the bundle size containing UI prefabs with TextMeshPro.
     

    Attached Files:

    Last edited: Oct 2, 2019
    phobos2077 and Novack like this.
  2. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    drag the contents of the Resources folder into an addressables group. At that point Addressables will tell you "you cannot have addressable Resources, would you like us to move these to another folder", and then if you click yes, we'll move it.
    We have an "unfixable rule" in the analyze window that checks for this scenario.

    The long and the short of it is that Unity will put everything in Resources into your build. Unity also will require that all dependencies of bundles be in bundles. So you either have to move things out of Resources, or not have addressable items reference them.
     
  3. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,091
    The problem with that is, textmeshpro loads assets with resources.load. Making them addressable and renaming the resources folder will cause them to fail loading. As well as causing a popup to “import” the essentials again.
     
    phobos2077 and Kazko like this.
  4. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    Long term we are working on ways for packages to make their contents addressable. So then TMP could load via addressables. Until then, if TMP has to load from Resources, then you either need to accept duplication, so you can load the same content from addressables, or you need to not have anything addressable that depends on the thing in Resources. Not a great answer, but it's the reality of these systems.
     
    CosmicStud likes this.
  5. funbites

    funbites

    Joined:
    Oct 9, 2015
    Posts:
    17
    So are there any plan to fix this?
     
  6. vvorkCase

    vvorkCase

    Joined:
    Apr 25, 2019
    Posts:
    3
    unity always have plans for fix problems))
     
  7. arturaz

    arturaz

    Joined:
    Mar 28, 2013
    Posts:
    30
    A workaround is to set it in runtime using reflection.

    Helper:
    Code (CSharp):
    1. using System.Diagnostics;
    2. using System.Reflection;
    3. using TMPro;
    4.  
    5. namespace Game.code.utils {
    6.   public static class TextMeshProUtils {
    7.     static readonly FieldInfo settingsFieldInfo;
    8.  
    9.     public static TMP_Settings settings {
    10.       get => (TMP_Settings) settingsFieldInfo.GetValue(null);
    11.       set => settingsFieldInfo.SetValue(null, value);
    12.     }
    13.  
    14.     static TextMeshProUtils() {
    15.       settingsFieldInfo = typeof(TMP_Settings).GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
    16.       Debug.Assert(settingsFieldInfo != null, nameof(settingsFieldInfo) + " != null");
    17.     }
    18.   }
    19. }
    Editor code:
    Code (CSharp):
    1.  
    2. using Game.code.control.entry_point;
    3. using Game.code.utils;
    4. using UnityEditor;
    5. using UnityEngine;
    6.  
    7. namespace Game.code.Editor {
    8.   [InitializeOnLoad]
    9.   public static class InitTextMeshPro {
    10.     static InitTextMeshPro() {
    11.       if (!TextMeshProUtils.settings) {
    12.         // Can't use our logger here because it's not initialized here.
    13.         Debug.Log("Loading text mesh pro settings in editor.");
    14.         var data = InitializerData.load();
    15.         TextMeshProUtils.settings = data.textMeshProSettings.editorAsset;
    16.       }
    17.     }
    18.   }
    19. }
    20.  
    Game code (do before using TextMeshPro):
    Code (CSharp):
    1.               var tmpSettings = "...get your settings from somewhere, like asset bundle...";
    2.               TextMeshProUtils.settings = tmpSettings;
     
    Last edited: May 27, 2020
    ZhiNuo, phobos2077 and Xarbrough like this.
  8. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    54
    What works for me is removing all references to FontAssets and SpriteAssets from the TextMeshPro Settings. Leave the settings in the Resources. That is fine when no big Asset is referenced and works with the existing code.

    Put your Materials/Fonts/SpriteAssets in Addressables and load them at the start of your game. Then you can use the
    TMPro.MaterialReferenceManager to add the loaded Assets. TextMeshPro is clever enough to look there after it can't find any default font referenced by the settings.

    I tagged all my Font Assets with the label "fonts" in the Addressables Groups window.

    Then use this code to load it:
    Of course you want to wait until this stuff is loaded before showing some texts

    Code (CSharp):
    1. var fontHandle = Addressables.LoadResourceLocationsAsync("fonts", typeof(ScriptableObject));
    2. fontHandle.Completed += fontLocations =>
    3. {
    4.     foreach (IResourceLocation location in fontLocations.Result)
    5.     {
    6.         string locationPrimaryKey = location.PrimaryKey;
    7.         Addressables.LoadAssetAsync<TMP_FontAsset>(locationPrimaryKey).Completed +=
    8.             font =>
    9.             {
    10.                 MaterialReferenceManager.AddFontAsset(font.Result);
    11.             };
    12.     }
    13. };
    Cheers
     
  9. JDMulti

    JDMulti

    Joined:
    Jan 4, 2012
    Posts:
    384
    Anything changed for TextMeshPro? It has been a while since it was addressed.

    Currently working on a project where we have a lot of fonts (mobile game). Using addressables for TMPro would be really usefull.
     
  10. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    I tried your solution, but SpriteAsset doesn't seem to work. I'm calling MaterialReferenceManager.AddSpriteAsset but I see XML text in place of sprites. Did you encounter similar issue?

    Edit: It seems the issue is that we use format <sprite name="xxx">. This format only works when there is a default sprite asset specified in Settings.. So I guess I'll have to move the entire settings asset out of Resources...

    Edit: solution from @arturaz seem to work better. The only downside is that you can't access TMP Settings from the Project Settings window and the "import essentials" button is active.. but as long as you don't press the button it's ok and everything works.

    I find it weird that such essentials two official packages don't play nice with each other. Looks like something for the TMP devs to look at.
     
    Last edited: Sep 7, 2021
  11. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    54
    For SpriteAssets this is my assign code:

    Code (CSharp):
    1. int sheetHashCode = TMP_TextUtilities.GetSimpleHashCode(spriteSheet.name);
    2. MaterialReferenceManager.AddSpriteAsset(sheetHashCode, spriteSheet);
    I then use this markup to get the sprite rendered:
    <sprite=\"{spriteSheet.name}\" name=\"{spriteName}\">


    spriteSheet is the Asset in the project directory. So those names have to match.

    I hope this still helps but good that you found a other solution.
    I agree that this should have a high priority...
     
    xucian and phobos2077 like this.
  12. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    In my case it was a worst option because the project is old and there are a lot of sprite references throughout and they use markup format without the sheet name. I didn't want to go and change them all. Also shorter format is more convenient if we use just one sprite sheet.
     
  13. KrcKung

    KrcKung

    Joined:
    Jul 18, 2017
    Posts:
    56
    Hello, do u guy hav issue regarding the draw calls as well, if using Text Mesh Pro in addressable? Coz one of our project encounter similar issue as the draw calls go ridiculously high and worst of all, we only can get the correct draw calls count from the build with dev mode + Frame debugger

    Tried using "Use Existing Build" to simulate it and still not able to simulate in editor (the draw calls count doesn't match), one of the symptom is it somehow not able to load Text in the build.
     
  14. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    I had to expand solution to support downloading fonts for certain languages (Japanese and Korean, about 15MB each) based on current language and then had to use more reflection to inject them into instantiated copy of TMP_Settings object's Fallback Font Assets list... Such a mess, but it kind of works. Except now I'm missing some characters. Have anyone tried to do something like this at all? Maybe there's some extra step involved into injecting fallback fonts at runtime?
     
  15. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    970
    I haven't, but my Emoji support relies on injecting fallback sprite sheets at runtime and getting that to work correctly involved modifying TMPro so many times that I don't even remember what all of my changes are.
     
    phobos2077 likes this.
  16. CosmicStud

    CosmicStud

    Joined:
    Jun 13, 2017
    Posts:
    55
    Is TMPro addressable yet? Pretty please lol ;)
     
    chriseborn likes this.
  17. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    Nope. After some analysis and discussion I think the best solution now is to code the support yourself into the local copy of the TMP package.
     
  18. Dasp

    Dasp

    Joined:
    Sep 25, 2012
    Posts:
    38
    Any ETA for adding this feature to TMP pro? @Stephan_B. Would be really helpful to not have duplicated font assets when using Addressables.
     
  19. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    836
    rabishan_unity likes this.
  20. Developer1999-1

    Developer1999-1

    Joined:
    Oct 27, 2020
    Posts:
    36
    Just spent 2 days trying to figure out why the bundle file size is so large only to find out about this. It makes my current bundle size bloat to 3 times its size. And if I were to add Japanese support, it would only grow larger. Addresable team, please......
     
    rabishan_unity likes this.
  21. Procyonx_

    Procyonx_

    Joined:
    Mar 7, 2017
    Posts:
    5
    Any updates?
     
    NyanGamedev and rabishan_unity like this.
  22. AleBraFinGroup

    AleBraFinGroup

    Joined:
    May 17, 2023
    Posts:
    9
    Just got into this problem and it still hasn't been fixed. upload_2023-10-19_17-58-10.png
    This is why Unity is mocked relentlessly by devs.
    I'll try to apply some of the solutions proposed on this thread and report on it. Hopefully.
     
  23. AleBraFinGroup

    AleBraFinGroup

    Joined:
    May 17, 2023
    Posts:
    9
    In the end I opted to do something preeeetty stupid, since I just need the FontAsset to show the text under the in-world GUI for the VR game I wanted to make, and I already know that my GUI font will always be the same for all GUIs in the world (so it won't change post-release).

    Since loading te TextMeshPro component from addressables loads also the font name (even if it doesn't have a reference to it), I can just load it from resources.

    upload_2023-10-20_11-20-5.png

    It's pretty dumb and presupposes that the font must be shipped with the game, but oh well, I have other stuff to work on.

    It's still aggravating that Unity hasn't fixed such blatant incopatibility between its systems in years. Come on. We shouldn't require these kind of hacks.
     
  24. icaro56

    icaro56

    Joined:
    Apr 4, 2018
    Posts:
    6
    Is there no official solution yet for this in Text Mesh Pro duplications with Addressable?
     
    chriseborn likes this.