Better Text Typeout in Unity

Text typeout, or the “typewriter effect,” is a popular way to spruce up text delivery in games. It’s pretty simple to add and can be done in just a few lines of code. The common Unity implementation probably looks something like this:

    public Text label;
    public float timeBetweenCharacters = 0.15f;
    private IEnumerator TypeoutCoroutine(string content)
    {
        var index = 0;
        while (index < content.Length)
        {
            index++;

            this.label.text = content.Substring(0, index);

            yield return new WaitForSeconds(this.timeBetweenCharacters);
        }
    }

At some interval, advance a counter up to the length of the total content to display. Assign a subsection of our content, from 0 to the current index, to the Text component’s Text property. Repeat until the whole string is displayed.

But while this definitely gets us a working typewriter effect, it’s not perfect. Words that expand past the bounds of the Text component while animating will suddenly jump to the next line.

This mid-word wrapping simply looks wrong. Things get even more distracting if “Best Fit” font sizing is enabled. The total content will continually shrink as more characters are added.

Luckily, there’s a fairly simple alternate implementation that looks much better. Instead of changing the actual content of the Text component every update, we can take advantage of the “Rich Text” property to reveal a subset of the content and hide the rest using transparency.

    public Text label;
    public float timeBetweenCharacters = 0.15f;
    private IEnumerator TypeoutCoroutine(string content)
    {
        var index = 0;
        while (index < content.Length)
        {
            index++;

            this.label.text = content.Insert(index, "<color=#FFFFFF00>") + "</color>";

            yield return new WaitForSeconds(this.timeBetweenCharacters);
        }
    }

Now, instead of copying a subset of the total content, we use the whole string but add a markup tag into it at the current index. This will change the color of all following characters until the close tag is reached. What color we pick for “hidden” doesn’t really matter, as long as it’s in the format xxxxxx00 – where the last two digits set the alpha to 0 / transparent.

The color of the rest of the text is driven by the Text component’s Color property. The content layout (and Best Fit font size, if applicable), are calculated on the full content string, so those properties don’t change while we’re moving the markup tags around. This produces a much cleaner and more consistent result.

Because the insert-text is easily configurable (just pull it out into a variable), we could apply this same technique to other situations where text color might change over time, like karaoke lyrics.

Quick note: if you’re applying a Shadow to your Text component, make sure the “Use Graphic Alpha” property is set to true, or the transparent letters will be unintentionally revealed!

Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *