Dear developers, recently we get various reports about text rendering issues on production. While we continue to work on optimizations for general text rendering, we’d also like to give some tips for better performance that will always be applicable.
Types of Text Issues
Text constantly flickering
When rendering text, font rasterization is usually involved. This is the process of creating a bitmap image from a vector description of a glyph (letter/symbol) in the form of a TrueType font (.ttf). Since text needs to be crisp, these images are always made at the exact size they will be rendered at, to avoid scaling artifacts. This means that there can be multiple images for the same glyph, at different font sizes. The size is also affected by your device’s pixel density (DPI scale), which can be higher on mobile devices.
These images are all stored in one large texture, called the font atlas, that’s used for all text rendering. When this texture runs out of space, you will start seeing artifacts like text on screen constantly flickering. This occurs most often on mobile, where devices have a higher DPI scale.
This flickering happens because when the font atlas gets full, it will delete old glyphs to make room for the new ones. If there are too many glyphs at once though, there might not be enough space to fit all of them.
To avoid this happening, it’s best to avoid using too many combinations of glyph, font, and text size at the same time. A lot of the best practices listed below can help with that.
Constant re-layouts that take up considerable time
Sometimes there are profiler labels called “Text Shaping + Layout” that show up in the microprofiler that can take a lot of time each frame. This usually happens when:
- Many scale-sized BillboardGui objects containing text are shown on screen at the same time.
- Typewriter animations that are constantly changing text content being used on multiple instances at once.
- Tween animations that are constantly changing text size.
Relayouts only occur when something in your GUI has changed. This can be from a script, a TweenService tween, from the camera moving (with BillboardGui), or from the player interacting with the GUI.
Best Practices for Text
Set MaxDistance on BillboardGui
A common issue we see in games is having dozens, or even hundreds, of BillboardGuis being rendered that aren’t even visible on the screen, but still impact performance. This is often because they’re in another room, but are occluded by a wall.
Setting the MaxDistance property will cause the UI to stop rendering when it’s too far away from the player, which should help reduce the number of BillboardGuis being rendered at once.
Choose smaller text sizes in SurfaceGuis
Instead of setting TextSize to 100 on your SurfaceGuis to make the text bigger, consider lowering the PixelsPerStud property on your SurfaceGui. This will make all Offset sized objects in that SurfaceGui larger, and can allow you to use a smaller TextSize, saving space in the font atlas.
Avoid TextScaled when possible
The TextScaled is useful for making sure that text will fit in your game, but it comes with a performance and memory cost. You should consider making the text size fixed and using AutomaticSize instead.
A common belief is that you have to use TextScaled for text to be readable on phones, but this isn’t the case. DPI scaling makes sure that sizes of 20 or above are readable no matter what device you’re on.
TextScaled takes about 10x more time to layout, and this impact can be visible in the microprofiler. It also causes your game to use more unique font sizes for the same glyphs, causing more problems for memory usage.
There are times when TextScaled is necessary, like scaled BillboardGuis. It’s more important to reduce usage than to try to completely eliminate it.
Avoid tweening TextSize
Constantly tweening text sizes for animations are potentially game-breaking. As mentioned above, this contributes to both overflowing the font atlas (due to a unique font size being used each frame) and frequent re-layouts per frame.
Avoid using too many variations of Fonts and TextSizes
Both design-wise and engineering-wise, it is beneficial to have limited variations of text style (font, text size) across the board. It will make your UI design cleaner as well as make good use of the available texture space.
This has become a bigger problem as we’ve added support for more fonts. It’s best to pick a few that fit your project, and stick to them.
Use MaxVisibleGraphemes for typewriter animations
A lot of existing tutorials and example code for typewriter animations have you constantly change the Text
property using string.sub
each frame. This forces a relayout of the text, and can cause problems with localization tools.
We recently shipped the MaxVisibleGraphemes property, which is a more performant way to do this.
We hope these tips help with your text performance!