GetFloat and AddSubTextObject rrrors when usign TextMeshPro

We have issue in our project with TextMeshPro in combination with Addressables. We moved all fonts and materials to addressables and removed them from resource folder. Since then we started getting errors when using Material tag in our texts. Visually text doesn’t appear at all until user restarts the game.
Error stack for GetFloat error. It doesn’t happen all the time, only sometimes and besides that everything works well.

Non-fatal Exception: NullReferenceException
0  ???                            0x0 get_name + 194 (UnityEngineObject.bindings.cs:194)
1  ???                            0x0 AddSubTextObject + 215 (TMP_SubMeshUI.cs:215)
2  ???                            0x0 SetArraySizes + 1467 (TMPro_UGUI_Private.cs:1467)
3  ???                            0x0 ParseInputText + 1965 (TMP_Text.cs:1965)
4  ???                            0x0 OnPreRenderCanvas + 1711 (TMPro_UGUI_Private.cs:1711)
5  ???                            0x0 Rebuild + 216 (TextMeshProUGUI.cs:216)
6  ???                            0x0 PerformUpdate + 215 (CanvasUpdateRegistry.cs:215)
7  ???                            0x0 SendWillRenderCanvases + 102 (UICanvas.bindings.cs:102)
8  ???                            0x0 ForceUpdateCanvases + 90 (UICanvas.bindings.cs:90)
9  ???                            0x0 EnsureLayoutHasRebuilt + 636 (ScrollRect.cs:636)
10 ???                            0x0 LateUpdate + 834 (ScrollRect.cs:834)
11 ???                            0x0 LateUpdate + 279 (ScrollRectExtended.cs:279)
12 ???                            0x0 ScrollRect:LateUpdate (UnityEngine.UI)

We are using newest TextMeshPro + Unity 2022.1.13

This is how we load materials when game starts

var fontMaterials = Addressables.LoadAssetsAsync<Material>("FontMaterial", null);
        asyncOperationHandles.Add(fontMaterials);

        fontMaterials.Completed += fonts =>
        {
            logger.Log($"[Materials] Found {fonts.Result.Count} materials");
            foreach (var material in fonts.Result)
            {
                int materialHashCode = TMP_TextUtilities.GetHashCode(material.name);

                if(!MaterialReferenceManager.TryGetMaterial(materialHashCode, out Material tempMaterial))
                {
                    MaterialReferenceManager.AddFontMaterial(materialHashCode, material);
                    logger.Log($"[Materials] Added {material.name} material");
                }
            }
        };

Any help solving this issue?

Any insight on this issue? @Stephan_B

Bump

Any chance you could submit a bug report with project or scene that would enable me to reproduce / take a closer look?

You could also provide me with an exported scene via PM if that is easier.

Of course, let me create a scene. I will send it in private message

This is an old thread, I know, but we just ran into this problem. I suspect everyone using Addressables + TMP hacks will run into this if they ever use strings with embedded <font> rich text tags.

In order to make the Addressables + TMP work together, you’ve likely had to hack in some method for TMP to load fonts/mats via addressables… and for now let’s just quietly ignore the fact that Unity should already support this out of the box given that these are two fundamental Unity systems.

Anyway. TMP’s MaterialReferenceManager holds cached references to mats/fonts/etc. for quick lookups for things like these <font> rich text tags. This is great and makes sense. However, if you ever unload the fonts/mats, say on a level change where you know they’re no longer being used, this manager never removes the now invalid entries from its cache. So it thinks all these assets are cached, but the asset references are null and you will get an exception the next time text with a re-used embedded <font> tries to render.

An easy (lazy) fix for this issue is to add logic to TMP’s MaterialReferenceManager such that upon any query we not only check if the key exists but also check that the value is not null. This is what we did… it’s pretty simple and it works great. Unfortunately, it requires moving the TMP package into your project so you can edit the source directly, which kind of sucks.

I’d suggest someone at Unity take 10 minutes to make the cache a bit more robust like I’ve described, it’s pretty trivial and pretty safe. It would also be nice to get the fix in a new, official 3.0.x release instead of just jamming it into another 3.2.x preview (which has been in preview for ~3 years now?..).

Hope this helps someone.