TextMesh Pro requires font assets to be placed in a Resources magic folder:
We have to use asset bundles in our project. This means assets are pulled-in to asset bundles through Unity’s dependencies system.
This initially caused that a lot of asset bundles pulled in a copy of all TextMesh Pro font assets from the resources folder, wasting a lot of disk and runtime memory.
In order to avoid that these font assets are stored in more than one asset bundle, I marked the “Resources/Fonts” directory to be stored in a separate asset bundle too.
This reduced the number of copies of the same font assets to “only two”. Two because one copy comes from the asset bundle and the other one from the Resources folder.
How can I get rid of the second copy in memory? I only want to have TextMesh Pro font assets in memory once.
Thanks for the quick reply. I don’t think we use the font-tag yet, but I know that we do use the sprite-tag.
Have you thought about adding a callback to TextMeshPro, to allow usercode to load a requested TextMesh Pro asset? I believe you could implement that with full backwards compatibility.
Here is the idea that popped into my head. It’s full backwards compatible and it seems it would be a few and simple code changes only to the TMP code.
In TMP_Settings or wherever you see fit, add a callback where the user can add his/her custom loading method. In order for TextMesh Pro to load resources internally, it does not call Resources.Load() anymore, but TMP_Settings.LoadResource().
public class TMP_Settings : ScriptableObject
{
public static System.Func<string, System.Type, UnityEngine.Object> loadResource;
internal static T LoadResource<T>(string assetName) where T : UnityEngine.Object
{
T result = default;
if (loadResource != null)
result = loadResource(assetName, typeof(T)) as T;
if (result == null)
result = Resources.Load<T>(defaultFontAssetPath + assetName);
return result;
}
}
In our game code, we could then do things like:
Code
The duplication is typically the result of how the AssetBundle is setup. For instance, if you bundle 2 font assets, each bundle will include the shaders thus resulting in duplication of resources. To avoid this, you would create a separate bundle that only includes the shaders where the other two bundles have a dependency on this shader bundle.
Can you provide more information / some images showing how your bundle is setup?
TMP Settings asset file is located under Assets\TextMesh Pro\Resources folder, which means it is embedded within the build target.
TMP Settings is referencing a Default Font Asset file (Resides in Assets\Fonts and contains a font atlas texture). Due to this reason, the font asset file is also embedded in the build, and loaded into memory on startup.
In addition, the same Default Font Asset file in included in an asset bundle. The reason for that, is that lots of prefabs are using this font file and they are a part of an asset bundle, so if this file is not included in an asset bundle it will automatically be added to their asset bundle (and in case of multiple asset bundle, it may be duplicated many times).
Possible solution, please review the following suggestion:
During editor time, TMP Settings will continue to reference the default font asset file (so that new text objects use it).
Before building a target version, this reference will be deleted (Can’t be done in code, please add support).
On application run time, after font asset file is loaded from asset bundle, startup code will set the default font asset file into TMP settings (Is this really needed??? Again support from your side is needed here)
This way there will only one copy of this asset in memory.
@Stephan_B
I have tried the suggested solution above (manually removing the reference before the build, because it is impossible by script for now) and it works. The duplication of font atlas in memory is gone.
It would be great if you can add support in code so the default font asset can be assigned and removed via code.
As long as we don’t use AddComponent during runtime, we are safe.
Alternatively, if we set the default font asset in TMP Settings after it is loaded from asset bundle (once scripting support is in place), we can also use AddComponent at runtime.
No plans right now to support them directly in TMP.
However, I do plan on adding a TMP Resource Manager where users will be able to implement their own loading of TMP related resources from AssetBundles, Addressables or any other source and then to subsequently add them to the TMP Resource Manager which will enable TMP to use them regardless of how they were loaded or where they came from.
We have a similar issue, in that we include the font asset (.otf, for a dynamic font) in an AssetBundle so that it will not be duplicated into multiple ABs. But it is. Despite being included in, say, “project_fonts”, it is getting included in every other AB that uses the TMP Font Asset. Since the particular font in question is for languages with larger character sets, it is huge (11MB), so our build is over 55MB bigger for no good reason that I can see, and as we add more content, it will just be duplicated more times.
I have created a separate, tiny, project to illustrate the problem. I have reproduced it in the latest 2019 and 2018 LTS builds, and submitted a bug (Case 1228188). @Stephan_B it would be great if you could take a quick look to at least ensure it is appropriately triaged.