Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug I've made a Dialogue system and it's bugging out

Discussion in 'Scripting' started by PanicMedia, Jul 23, 2021.

  1. PanicMedia

    PanicMedia

    Joined:
    Dec 6, 2020
    Posts:
    37
    I've made a dialogue system and for some reason once the first bit of dialogue comes off it throws out a bunch of random characters and then comes up with the error:
    IndexOutOfRangeException: Index was outside the bounds of the array.
    Dialog.Update () (at Assets/Scripts/Dialog.cs:27). Now in the tutorial I'm going off the person making it used a continue button but i've tried to make it so that it continues automatically. Here's my script

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5.  
    6. public class Dialog : MonoBehaviour
    7. {
    8.   public TextMeshProUGUI textDisplay;
    9.   public string[] sentences;
    10.   public float typingSpeed;
    11.   private int index;
    12.  
    13. /// <summary>
    14. /// Start is called on the frame when a script is enabled just before
    15. /// any of the Update methods is called the first time.
    16. /// </summary>
    17. void Start()
    18. {
    19.     StartCoroutine(Type());
    20. }
    21.  
    22. /// <summary>
    23. /// Update is called every frame, if the MonoBehaviour is enabled.
    24. /// </summary>
    25. void Update()
    26. {
    27.     if(textDisplay.text == sentences[index])
    28.     {
    29.  
    30.         Invoke("NextSentence", 2.0f);
    31.     }
    32.     else
    33.     {
    34.       return;
    35.     }
    36. }
    37.   IEnumerator Type()
    38.   {
    39.       foreach(char letter in sentences[index].ToCharArray())
    40.       {
    41.           textDisplay.text += letter;
    42.           yield return new WaitForSeconds(typingSpeed);
    43.          // NextSentence();
    44.       }
    45.   }
    46.  
    47.   public void NextSentence()
    48.   {
    49.       if(index < sentences.Length)
    50.       {
    51.           index++;
    52.           textDisplay.text = "";
    53.           StartCoroutine(Type());
    54.  
    55.       }
    56.       else
    57.       {
    58.           textDisplay.text = "";
    59.       }
    60.   }
    61. }
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,890
    Code (CSharp):
    1.     if(textDisplay.text == sentences[index])
    2.     {
    3.         Invoke("NextSentence", 2.0f);
    4.     }
    Because this code is in Update(), you will schedule NextSentence() to run every frame for at least 2 seconds. If your framerate is 60, that means it will run about 120 times. That's surely going to throw some logic off.
     
  3. PanicMedia

    PanicMedia

    Joined:
    Dec 6, 2020
    Posts:
    37
    I have tried increasing the time and it still does it at the end of the wait
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,890
    The time isn't the problem. The fact that you're starting the invoke every frame is the problem. You just want to do it once. It shouldn't really be in Update it should be started in Type() after the last character is printed. you don't need Update at all.
     
    PanicMedia likes this.
  5. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You never initialize the value of index before you use it.
     
    PanicMedia and PraetorBlue like this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,518
    There's a lot of pretty tangled multiple-start coroutine stuff in there, plus that issue Praetor pointed out with using Invoke every frame.

    You might have more luck with a simpler approach, something with:

    Code (csharp):
    1. private int currentSentenceNumber;
    2. private int currentLetterNumber;
    ... to control what is happening.

    Then for each sentence:
    --> for as long as there is letters to consume in a given sentence
    ----> add one letter to the output
    ----> display what you have so far
    ----> pause a fraction of a second (yield)

    Just one big coroutine, started one time. No invokes either. Invoke is dangerous.

    At the end of it all, set a simple variable to say you are done:

    Code (csharp):
    1. public bool Completed;