Skip to content

Instantly share code, notes, and snippets.

@unitycoder
Last active April 11, 2024 08:11
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save unitycoder/19625fed364a39cb278f to your computer and use it in GitHub Desktop.
Save unitycoder/19625fed364a39cb278f to your computer and use it in GitHub Desktop.
Type out UI text one character at a time
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
// attach to UI Text component (with the full text already there)
public class UITextTypeWriter.cs : MonoBehaviour
{
Text txt;
string story;
void Awake ()
{
txt = GetComponent<Text> ();
story = txt.text;
txt.text = "";
// TODO: add optional delay when to start
StartCoroutine (PlayText());
}
IEnumerator PlayText()
{
foreach (char c in story)
{
txt.text += c;
yield return new WaitForSeconds (0.125f);
}
}
}
@unitycoder
Copy link
Author

@qba210
Copy link

qba210 commented Jul 26, 2022

Added an option to disable typing sound.
Also added a volume slider.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text;
using System;
using TMPro;

[RequireComponent(typeof(TextMeshProUGUI))]
public class UITextTypewriter : MonoBehaviour
{
    [Header("Typing Settings")]
    public TextMeshProUGUI text;
    public bool playOnAwake = true;
    public float delayToStart;
    public float delayBetweenChars = 0.125f;
    public float delayAfterPunctuation = 0.5f;
    private string story;
    private float originDelayBetweenChars;
    private bool lastCharPunctuation = false;
    private char charComma;
    private char charPeriod;
    private char charEmpty;
    [Header("Audio Settings")]
    [Tooltip("When true requires AudioSource on this object.")]
    public bool useAudio = true;
    [Range(0f, 2f)]
    public float volume = .3f;
    [Tooltip("GameObject with AudioSource component.")]
    public GameObject AudioTypping;
    private AudioSource TyppingFX;

    void Awake()
    {
        if (useAudio) {
            TyppingFX = GetComponent<AudioSource>();
            TyppingFX.clip = AudioTypping.GetComponent<AudioSource>().clip;
        }

        text = GetComponent<TextMeshProUGUI>();
        originDelayBetweenChars = delayBetweenChars;

        charComma = Convert.ToChar(44);
        charPeriod = Convert.ToChar(46);
        charEmpty = Convert.ToChar(" ");//Convert.ToChar(255);

        if (playOnAwake)
        {
            ChangeText(text.text, delayToStart);
        }
    }

    //Update text and start typewriter effect
    public void ChangeText(string textContent, float delayBetweenChars = 0)
    {
        StopCoroutine(PlayText()); //stop Coroutime if exist
        story = textContent;
        text.text = ""; //clean text
        Invoke("Start_PlayText", delayBetweenChars); //Invoke effect
    }

    public void StartTypewriter()
    {
        StopCoroutine(PlayText()); //stop Coroutime if exist
        text.text = ""; //clean text
        Invoke("Start_PlayText", delayBetweenChars); //Invoke effect
    }

    void Start_PlayText()
    {
        StartCoroutine(PlayText());
    }

    IEnumerator PlayText()
    {

        foreach (char c in story)
        {
            delayBetweenChars = originDelayBetweenChars;

            if (lastCharPunctuation)  //If previous character was a comma/period, pause typing
            {
                if (useAudio) TyppingFX.Pause();
                yield return new WaitForSeconds(delayBetweenChars = delayAfterPunctuation);
                lastCharPunctuation = false;
            }

            if (c == charEmpty || c == charComma || c == charPeriod)
            {
                if (useAudio) TyppingFX.Pause();
                lastCharPunctuation = true;
            }

            if (useAudio) TyppingFX.PlayOneShot(TyppingFX.clip, volume);
            text.text += c;
            yield return new WaitForSeconds(delayBetweenChars);
        }
    }
}

@spider853
Copy link

spider853 commented Apr 4, 2023

Here is a simplier approach, without audio

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

[RequireComponent(typeof(TextMeshProUGUI))]
public class ScrollText : MonoBehaviour
{
    public string GameSceneName;
    public float InitialDelay = 0.1f;
    public float CharWait = 0.5f;
    public float CommaWait = 0.3f;
    public float PeriodWait = 0.5f;

    TextMeshProUGUI textMesh;
    string text;

    // Start is called before the first frame update
    void Start()
    {
        textMesh = GetComponent<TextMeshProUGUI>();
        text = textMesh.text;
        textMesh.text = "";
        StartCoroutine(TypeText());
    }

    IEnumerator TypeText()
	{
        yield return new WaitForSeconds(InitialDelay);
        foreach (char c in text)
		{
			textMesh.text += c;
            yield return new WaitForSeconds(CharWait);
			if (c == ',')
				yield return new WaitForSeconds(CommaWait);
			if (c == '.')
				yield return new WaitForSeconds(PeriodWait);
		}
        SceneManager.LoadScene(GameSceneName);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment