Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

TextMesh Pro TextMesh Pro - Font atlases memory leak?

Discussion in 'UGUI & TextMesh Pro' started by Znol, Jun 23, 2022.

  1. Znol

    Znol

    Joined:
    May 10, 2020
    Posts:
    6
    My problem is that Unity creates a bunch of copies of the same atlas, materials, and ScriptableObject, as you can see in the MemoryProfiler screenshots. All of them take up additional memory, which I would like to avoid. The number of copies increases if I open different objects using the TextMeshPro asset and return to the previous game state. For example, at first I had 12 copies, I opened various windows with text, returned to the previous state of the game and already have 14 copies.

    Dmitry Copies.PNG

    Objects using TextMeshPro use the same Font Asset, may use different Material Presets with slight changes in font settings.

    TMPro1.PNG

    Also, as Fallback atlases, this atlas uses two others with Korean and Japanese characters, which are not on the game screen, but they still lie in memory, and there are several copies of them, which is strange for me, I expected that they would not be here at all. The Main Atlas has all the symbols displayed on the screen and should not use Fallback atlases at this case.

    Ko&Ja Atlases.PNG

    There is one reference for each copy, which is difficult to read. By the way, these two atlases work in the "Dynamic" fill mode and generally weigh 32MB each, since they were created in the size of 4096x4096 (I suppose they weight this is due to the fact that they are not completely filled).

    Ko&Ja Links.PNG KoreanLinks.PNG

    So, I want to know more deeply what is happening here and how I can save memory by ceasing to create copies of the same atlases.

    Additional information: I use the I2 Localize asset to translate texts. It replaces characters in TextMeshPro text when changing language using the text data from the asset's data.
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    It is hard to tell what might be happening as for instance, manipulating material properties via script can easily result in new instances of material being created.

    In order to try to narrow down what might be happening, I would suggest using a single font asset with a few material preset. At first don't assign any fallback to this font asset just to see if you observe the same behavior.

    In terms of memory savings / overhead, I recommend using Dynamic or Dynamic OS font assets with "Clear Dynamic Data on Build" and "Multi Atlas Texture" enabled where the Atlas Texture size are no larger than 1024 x 1024.

    When Dynamic font assets are created or when their Dynamic Data is cleared or when the font asset is Reset via the font asset context menu, their main atlas texture is resized to size 0 with all potential additional atlas textures deleted. When the first glyph is added to the atlas texture, the texture is resized to whatever size you specified in Generation Settings.

    Until a first glyph is added to this dynamic font asset, its atlas texture will take no memory. Once this new glyph is added, the texture will then take whatever memory it should where for instance a 1024 x 1024 will be 1MB x 2 since it is read enabled. Although we only added a single glyph, the memory overhead of the texture is the same as a full texture.

    Let's assume this dynamic font asset was used as fallback and was of size 4096 x 4096, its memory overhead would be 16MB x 2 (32MB) once a first glyph is added to it. Now if during a play session, this atlas texture was to remain mostly empty, we would be wasting all of this memory overhead. In this case, we would have been much better off using a smaller atlas texture size.

    Dynamic font assets that have Clear Dynamic Data on Build enabled, will be shipped with their atlas texture at size zero. At the start of each play session, they will be back to this ship state. As such, you only have to concern yourself with how many potential glyphs will be added to it in a single play session and how fast it will fill up. For instance, a 1024 x 1024 atlas texture can contain over 200 glyphs at a sampling point size of 90 with padding of 9. If this fallback is there to handle user input then you will minimize the memory overhead while it fills up and with Multi Atlas Texture enabled, additional atlas textures will be created in the even the first one gets full.

    The only time you should consider larger atlas texture for dynamic font assets is when your sampling point size and padding make it where you can fit more than 100 glyphs per atlas textures.

    Lastly, all known text in the project, that is text contained in your UI, Menus, etc. should be packed in static font assets. Dynamic font assets should be used to handle unknow text / user input. Static font asset should be broken up by groups of languages or individual languages but again only contain the known text.

    P.S. I have made several posts about this topics in the past with additional information about the use / combination of static and dynamic font assets.
     
  3. Znol

    Znol

    Joined:
    May 10, 2020
    Posts:
    6
    @Stephan_B Hello, thank you for your answer. We discovered that the problem was caused by Addressables Groups.
    Every time an adressable pack that referenced TextMeshPro assets was dumped into memory, a copy of the TextMeshPro assets were created. We created a separate adressable group that contains all TextMeshPro assets (Materials, Shaders, Font assets) and upload it at the start and now everything looks perfect!
     
    Stephan_B likes this.
  4. Dronjak

    Dronjak

    Joined:
    Dec 28, 2016
    Posts:
    7
    Hello, I'm having the same problem. I grouped all of the Font assets, Materials. However, the issue persist did you even grouped the TMP_SDF.shader maybe that will solve the issue?
     
    Last edited: Aug 9, 2023