Typing Text... in Unity

How to create a Typewriter Text effect in Unity

In Game Systems, Visuals by John FrenchUpdated 4 Comments

This article is part of a series on Dialogue in Unity.

When displaying written dialogue in a text box in Unity, it’s possible to type out each character one by one to create a kind of typing effect.

Which can be useful as, typically, displaying lines of text immediately can be a little less immersive than delivering them character by character, which creates a kind of flow to the speech as you read it.

But how does it work?

The simplest way to create a typewriter effect in Unity is by literally adding each character of a string to a text field one at a time, with a delay in between to create the typing effect.

The easiest way to do this is with a Coroutine, where a For Each loop is made to wait for each new character using the Wait For Seconds class.

Like this:

float charactersPerSecond = 5;

IEnumerator TypeText(string line)
{
    string textBuffer = null;
    foreach (char c in line)
    {
        textBuffer += c;
        dialogueText.text = textBuffer;
        yield return new WaitForSeconds(1 / charactersPerSecond);
    }
}

This works, but it’s, technically, framerate dependent, since it can only be accurate if the interval between each letter being typed is longer than the duration of each frame.

What this means is that the text can only be typed at a maximum speed of one character per frame, which, in many cases, might be fine.

But, if you want to create a very fast text effect, where characters can be perceived to be generated at a rate faster than one each frame, or you expect that a drop in the game’s framerate could affect how the text is displayed, then you may wish to generate it in a way that is independent of your game’s framerate.

One way to do this is by measuring how long each character should take to be displayed and use that amount of time to increment a timer value.

Then, the coroutine is only suspended when enough characters have been displayed that the total of their intervals is longer than the frame time, at which point the timer is reset and the frame is advanced, carrying over any excess time to keep the overall rhythm accurate.

Like this:

float charactersPerSecond = 90;

IEnumerator TypeTextUncapped(string line)
{
    float timer = 0;
    float interval = 1 / charactersPerSecond;
    string textBuffer = null;
    char[] chars = line.ToCharArray();
    int i = 0;

    while (i < chars.Length)
    {
        if (timer < Time.deltaTime)
        {
            textBuffer += chars[i];
            dialogueText.text = textBuffer;
            timer += interval;
            i++;
        }
        else
        {
            timer -= Time.deltaTime;
            yield return null;
        }
    }
}

Generally speaking, this method is easier to control, even though the only thing that’s changed is the way that time is measured.

Instead of checking if enough time has passed to add a new character, the function checks if enough characters have been added so that it can stop and wait for the next frame.

Which might be one, none, or multiple characters, depending on how fast you want them to appear to be typed.

This works in a similar way to how Fixed Update is scheduled, where multiple fixed updates may be triggered during a frame to make up for the fact that physics calls typically run at a different frequency to update calls.

It’s appropriate in this use case since, unlike when delaying a function or doing something every few seconds, the frequency of the appearing letters is going to usually be as fast, or faster, than the framerate of the game.

Now I want to hear from you

How are you displaying text in your game?

Are you using a typewriter effect with a coroutine, or are you using a different method?

Whatever it is, let me know by leaving a comment.

John French profile picture

by John French

Game audio professional and a keen amateur developer.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

How this content was created

This article was written using first-hand research and experience, without the use of AI. For more information on how Game Dev Beginner articles are written, see my writing policy.

Comments

  1. Nice to see an article on this! I actually implemented a similar effect in my game, but one thing I noticed is that if you have multi-line text, and you update text as you do here, then when there’s a line break it’ll start on the wrong line before jumping down to the right one.

    The way I got around this was by instead having the full text always there, but adding an “ at the point in the text where I needed to stop, and updating that each frame. (You don’t need to close it with “ since it goes till the end of the line). This way the lines are already broken as they will be when the full text is written out.

    This obviously only works if you’re using TextMeshPro since it needs to support rich text.

  2. Whoops, apparently the “ removes the internal text. I’ll just type it out:

    You’ll want to add a tag at the point where you need the text to stop. No need for the closing tag.

  3. Ack, still removes it. Ok, I’ll try it this way,

    You’ll want a [less-than-sign]alpha=#00[greater-than-sign] tag at the point where you need the text to stop.

    Last try haha

Leave a Comment