TextMeshPro renders text wrong?
When you want to display text in Unity (starting circa version 2021,) the text components default to TextMeshPro (TMP).
TextMeshPro makes you create an asset called “Font Asset” before you can display anything.
It contains a Font Atlas, which is a collection of pre-rendered letters packed into a single image,
whose mapping TMP keeps track of to display the text afterwards.
When making the atlas, you can set the sampling point size (SPS), which is the font size used to pre-render the letters. This also translates to the biggest font size at which TMP can safely display the letters (for the most part). For example, smaller SPS sometimes characters to be positioned incorrectly. Bigger SPS requires larger atlas size, but it helps you avoid weird issues… or does it?
Let’s try an excessive case: we crank up the atlas size to maximum (8192 x 8192) and create the font atlas. With the auto sizing option for SPS, we should get a nicest result, right?
Of course, I did not add any font-related effects or shader effects or something related to that. This is a TMP text displayed with the default setting with the Font Asset we just created.
- Unity 2021.3.6f1
- TextMeshPro 3.0.6
Let’s see what happened
For this experiment, we use M+ Font (2p) which can be retrieved from Google Fonts (or directly from M+ Font distribution site)
We just created a Font Asset with the maximum possible atlas size. TMP’s Font Asset Creator reports the atlas information, so let’s take a look:
“Point Size” is the SPS that TMP has chosen for this atlas generation. It reports it’s 1394. Quite excessive, but let’s move on for now.
For comparison, let’s also create a Font Asset with a sensibly-sized atlas:
The SPS this time is just 23.
Now what happens if we display text using those fonts?
The label using the big font asset has catastrophically failed to render the text correctly!
This issue has been raised in Unity Forum; the SPS becomes larger as the atlas size gets bigger… and it becomes too big for the character to be way too tightly packed! Each character needs to be spaced out for TMP to work correctly. To space them out, you need to use, you guessed it, the Spacing property.
In the thread, the Sampling Point Size and Padding should satisfy the next formula:
SPS / Padding = 10
If you look at the log closely, this ratio is reported
The value here should say
10% or somewhere around that value.
SPS defaults to
Auto Sizing when you first introduce TMP to your project.
This means that TMP will adjust the SPS according to the Font Atlas size.
However, there is no way (and no apparent instructions) to set the Padding automatically (it defaults to 5 and can be as big as 64),
so it may fly under your radar.
If you only need ASCII, the size of 512x512 ~ 1024x1024 should do. If you choose to set your SPS yourself, you can control it further and you don’t even need to force the atlas to be a square. Just make sure that SPS/PD ratio is 10%, and find the atlas size that can pack the letters as tightly as possible.