Our Efficient Way

We had to dig inside Unity UI’s Text component mesh generation to understand how it works. As many, if not all game engines, Unity generates a mesh composed of a quad for each character of the text you’re displaying. Then it uses a texture generated from your type font to draw characters onto these quads.

Character quads

So, we deal here with the usual triad: mesh + material + shader. Going from there, the question is: What if we could alter the mesh generation process to add additional information for each character?

Setting this up

Our goal here is to give a kind of index to each displayed character. With that information, we will be able to use this index information in a custom shader that will not draw any part of the mesh past a specific index.

The best and easiest way to pass this new information is the second UV channel (UV1). By default, Canvas components give only the first UV channel to the shaders. So we have to set the Additional Shader Channels parameter of the Canvas component to include TexCoord1.

Canvas > Additional Shader Channels > TexCoord1

Altering the Mesh

We’re now ready to start altering the mesh by adding a second UV channel. Thanks to the IMeshModifier interface, we can modify meshes of UI components such as Text.

As long as your Text component does not have any cosmetic components such as Outline, the modification is fairly simple. You can safely split the vertices array in “groups of 4 vertices”, one for each character of your text.

Here is our code for this modification:

ProgressiveText with IMeshModifier

Associating a nuance of red to each index / character with a simple test shader makes the process more understandable.

Test representation of indices in red

The Shader Magic

Now everything is set up, we have to put the final touch to our system.

Our shader must be supported by the Text component. In order to achieve perfect compability, what’s best than taking the very own Text component’s shader as a base?

Nothing! So, we went looking for the UI/Default shader’s source code. All built-in shaders are available as a separate download for each version of Unity in the download archive.

The only thing we had to do is to add a new property to the shader to represent the display threshold. Every character with an index below this threshold would be displayed. Every index over wouldn’t. As we use a UV channel as the source of information, this threshold will be comprised between 0 and 1. We called it Character Phase.

Here is the resulting code:

ProgressiveText’s shader source code

The final step is to adapt our custom component script to support this new property, through the use of the IMaterialModifier interface.

And we’re done!