Trying to create random dialogue text from an array, and then making it write out slowly like a typewriter.

Hello, I’ve been stuck all day trying to make this work. I’m new to Unity, so I fully understand that this is probably a lot more complicated than it needs to be.

I have managed to make a working script where a random piece of dialogue gets chosen from an array and then gets written out on a dialogue box

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

public class RandomJadeDialogue : MonoBehaviour
{
    public GameObject dialogBox;
    public bool playerInRange;
    public string[] randomDialog = new string[30];
    public Text selectedDialog;

    void Start()
    {
       //(This is where all the array items are located)
    }

    string GetRandomDialog()
    {
        int random = Random.Range(0, randomDialog.Length);
        return randomDialog[random];
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && playerInRange)
        {
            if (dialogBox.activeInHierarchy)
            {
                dialogBox.SetActive(false);
            }
            else
            {
                dialogBox.SetActive(true);
                selectedDialog.text = GetRandomDialog();
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            playerInRange = true;
        }
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            playerInRange = false;
            dialogBox.SetActive(false);
        }
    }
}

but I would like to make it so that the text gets typed out, like in an old rpg. The way I have attempted to this so far has been making a new script where the code for the typewriting is, and within that script I’ve tried to find a way to GetComponent<Text>().text, but the code does not work.

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

public class TypeWriterEffect : MonoBehaviour
{
    public float delay = 0.1f;
    public string fullText;
    private string currentText = "";

    void Start()
    {
        StartCoroutine(ShowText());
    }

    IEnumerator ShowText()
    {
        for (int i = 0; i < fullText.Length; i++)
        currentText = fullText.Substring(0, i);
        GetComponent<Text>().text = currentText;
        yield return new WaitForSeconds(delay);
        Debug.Log("reached loop");
    }   
}

When I try to run the game, the log tells me “NullReferenceException: Object reference not set to an instance of an object”

I believe this to be because the Text that GetComponent<Text>().text is trying to Get starts out blank, and therefore there is no way for the program to know what text it should write out, but I’m also having a really hard time understanding how GetComponent works to begin with, so it could definitely be something else.

@vivi_blckrvr I would recomend watching Brackeys tutorial for a dialogue system. About 13 minitues in the video he explains how to slowly add letters one by one
https://www.youtube.com/watch?v=_nRzoTzeyxU

Though its an old question that popped up somehow:


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

public class TypeWriterEffect : MonoBehaviour
{
    public float delay = 0.2f;
    public string fullText;
    public string currentText = "";

    public Text text;

    void Start()
    {
        Canvas canvas = gameObject.AddComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceCamera;

        gameObject.AddComponent<CanvasScaler>();
        gameObject.AddComponent<GraphicRaycaster>();
        text = gameObject.AddComponent<Text>();

        Font arial;
        arial = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
        text.font = arial;
        text.fontSize = 48;

        StartCoroutine(ShowText());
    }

    IEnumerator ShowText()
    {
        for (int i = 1; i <= fullText.Length; i++)
        {
            currentText = fullText.Substring(0, i);
            text.text = currentText;
            yield return new WaitForSeconds(delay);
        }
    }
}

  • So the Text component can be added with AddComponent() or in the Inspector.

  • Canvas stuff is also added here to make it display the text when using the script on an empty GameObject.

  • The curly brackets were missing for the for loop, so only currentText = fullText.Substring(0, i); was executed in the loop.

  • The index was not correct in this case because Substring() takes the length of the substring as its second argument (i=0: no text is displayed, i=fullText.Length-1: last character is missing).