Bug with CanvasScaler "Reference Pixels Per Unit"

When creating a world-ui canvas you normally reduce the RPPU to something like 1 (down from the default 100) so UI images will not have huge pixels.

Unfortunately TextMeshPro does not seem to respect that setting, which causes problems later on.
A font-size of 16 should create symbols that are 16px in height, right?

But when you use the canvas scaler as it is intended you have to use font sizes like 0.015…

The intended behavior would be to that TMP factors in the canvas scale into the font size calculation. (or at least provide a bool flag in the global TMP options to turn that on or off)

Will the new version of TMP respect the “Reference Pixels Per Unit” on the CanvasScaler component?

The CanvasScaler “Reference Pixels Per Unit” setting only applies to Sprites that have a Pixel Per Unity setting and assigned to UI Elements like Buttons, Panels, etc. Text components like UI.Text and TMP are not affected by this setting.

The scale & size of the canvas affect the scale of text objects. In the future, I think it would make sense to support some DPI setting that could influence the point size on text objects but not sure yet how to handle that from a user functionality point of view.

I think what many people do to work around this problem right now is to simply scale the canvas itself instead of modifying the reference pixels per unit. That way you can adjust how big a font size of “16” really is in world-coordinates.

But it causes some problems later on.
For example if you have dialogs that have a 3D mesh associated with them (for example if you have a 3D box as background, or text on a globe, or on a car, or…) then you have to fiddle with the scale and keep it uniform across all your world space canvases. It quickly becomes a mess as soon as you actually go beyond the basic usage scenarios.

I hope you can find some way to provide some DPI / RPPU / “font scale” setting.
Even something as simple as a float property on each TMP text called “FontScale” or so would already solve this.

Do you perhaps know about any sort of workaround that we could use until (if) it is implemented?

If you are trying to mix text with 3D objects, I would simply use normal TextMeshPro objects “Create Menu - 3D Objects - TextMeshPro - Text” which are designed to work in WorldSpace just like the old TextMesh. As these text objects would be scaled and positioned relative to those 3D objects, you would not have to fiddle with any of this scaling.

In addition, this would also be more efficient then using a bunch of Canvases set to worldspace.

Yes we have tried that but unfortunately there are several issues that prevent this.

We actually want a canvas for layouting (vertical layout panel, …), we want the buttons and events, as well as the support for UI Images. Sure we could use normal sprites as well for the images, but then we’d have to do our own layout, and all in all it just becomes so much harder.

We would basically have to reinvent the wheel a number of times.
There will be 5 or so worldspace canvases at most (almost always only 0-2), so performance is not really a problem I think; getting things done is.

1 Like

This bug still exists (2019.3.12f1). It’s definitely a bug because “Text” and “Text - TextMeshPro” behave differently, was described: one honours the scaler’s Dyanmic Pixels Per Unit (“… such as Text” sats the Tooltip), the other ignores it completely. Seems TextMeshPro is yet another shiny new feature that’s never finished.

In the latest release of the TMP package contained in the TMP Essential Resources, there are new shaders with the Suffix SSD. These do not require scale to be passed to the shaders and will work as expected with the CanvasScaler.

Passing scale to the shaders results in more efficient shaders but can be problematic when object scale changes since there is not callback in Unity to detect scale changes on object. The CanvasScaler can also be a potential issue as it also affects the rendering scale.

The SSD shaders use screen space derivative which requires additional computations in the fragment shader thus making those not as efficient as the base shaders.