print text one character at a time with rich text

So i’m making a pretty simple text adventure game and when I output the text, I want it to print out one character at a time, like it’s being typed. I managed to figure that out but the only problem is I’m using rich to text to change the color and italicize a lot of the text. So the text I’m printing out looks like this:

"<color=blue>Enter house?</color>"

And i’m using a co routine to print it out like this:

IEnumerator printText(String txt)
 {
    for(int i=0; i<txt.Length; i++)
    {
       output.text = output.text + txt*;*

yield return new WaitForSeconds(0.1f);
}
}
So when it prints out, the < color > stuff doesn’t go away until the whole line is printed. Is there any way I can change the text color without this problem?

You can use this library. This works also for child tags.

https://github.com/majecty/Unity3dRichTextHelper

Here is an example.

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using RichTextSubstringHelper;

public class NewBehaviourScript : MonoBehaviour {
    [SerializeField]
    Text uiText;
    IEnumerator Start () {
        var firstText = "<color=blue>blah</color>x";
        for (int i = 0; i < firstText.RichTextLength(); i++)
        {
            yield return new WaitForSeconds(0.5f);
            uiText.text = firstText.RichTextSubString(i + 1);
        }
    }

}

Hey Tomasay,

Warning: Does not work with child tags.

I made a quick parsing function that will do what you’re asking. It’s not the best so anyone that wants to jump in and edit this script is more than welcome.

It basically wraps every character in the starting and ending tag so it creates more text than necessary.
So if you had text like this:

<color=red>Hello</color> everyone.
it would turn into
<color=red>H</color><color=red>e</color>... etc. 

Here’s the script:

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class DisplayDialog : MonoBehaviour
{
    public float delayTime = 0.1f;
    public Text paragraph;

    public void SetText(string text)
    {
        StartCoroutine(SetTextRoutine(text));
    }

    public IEnumerator SetTextRoutine(string text)
    {
        // reset the paragraph text
        paragraph.text = string.Empty;

        // keep local start and end tag variables 
        string startTag = string.Empty;
        string endTag = string.Empty;

        for (int i = 0; i < text.Length; i++)
        {
            char c = text*;*

// check to see if we’re starting a tag
if (c == ‘<’)
{
// make sure we don’t already have a starting tag
// don’t check for ending tag because we set these variables at the
// same time
if (string.IsNullOrEmpty(startTag))
{
// store the current index
int currentIndex = i;

for (int j = currentIndex; j < text.Length; j++)
{
// add to our starting tag
startTag += text[j].ToString();

// check to see if we’re going to end the tag
if (text[j] == ‘>’)
{
// set our current index to the end of the tag
currentIndex = j;
// set our letter starting point to the current index (when we continue this will be currentIndex++)
i = currentIndex;

// find the end tag that goes with this tag
for (int k = currentIndex; k < text.Length; k++)
{
char next = text[k];

// check to see if we’ve reached our end tags start point
if (next == ‘<’)
break;

// if we have not increment currentindex
currentIndex++;
}
break;
}
}

// we start at current index since this is where our ending tag starts
for (int j = currentIndex; j < text.Length; j++)
{
// add to the ending tag
endTag += text[j].ToString();

// once the ending tag is finished we break out
if (text[j] == ‘>’)
{
break;
}
}
}
else
{
// go through the text and move past the ending tag
for (int j = i; j < text.Length; j++)
{
if (text[j] == ‘>’)
{
// set i = j so we can start at the position of the next letter
i = j;
break;
}
}
// we reset our starting and ending tag
startTag = string.Empty;
endTag = string.Empty;
}

// continue to get the next character in the sequence
continue;

}

paragraph.text += string.Format(“{0}{1}{2}”, startTag, c, endTag);

yield return new WaitForSeconds(delayTime);
}
}
}