Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Auto Text Typer Slows Down

Discussion in 'Scripting' started by KnightRiderGuy, Jan 1, 2018.

  1. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    514
    I'm working with a method of auto typing information to display two, but something strange is happening.
    If I make this a separate project where I have some buttons on display one that call to the TextBoxManager script on a game object on a UI panel in display two everything works fine.


    BUT!! When I migrate this over to my main project the auto typing starts out fine when called but begins to slow down and eventually types each letter super slow....??
    And yet both projects my main and my test project are calling the auto type in exactly the same way.

    Any thoughts on what could cause this??

    Here is an example of my script:

    Code (CSharp):
    1. public float letterPause = 0.2f;
    2.     public AudioClip typeClick;
    3.     AudioSource audioSource;
    4.  
    5.     string message;
    6.  
    7.     public GameObject textBox;
    8.  
    9.     public Text theText;
    10.  
    11.     public TextAsset textFile;
    12.     //public TextAsset textFileTwo;
    13.  
    14.     public string[] textLines;
    15.  
    16.  
    17. // Message One
    18.     public void MessageOne ()
    19.     {
    20.         textFile = Resources.Load("BonnieBarstowInfoText") as TextAsset;
    21.         Debug.Log(textFile.text);
    22.  
    23.         audioSource = GetComponent<AudioSource>();
    24.         message = textFile.text;
    25.         theText.text = "";
    26.  
    27.         if (textFile != null)
    28.         {
    29.             textLines = (textFile.text.Split('\n'));
    30.         }
    31.         StartCoroutine(TypeText ());
    32.  
    33.  
    34.     }
    35.  
    36. IEnumerator TypeText ()
    37.     {
    38.         yield return new WaitForSeconds (2.5f);    // Wait Time
    39.         foreach (char letter in message.ToCharArray())
    40.  
    41.         {
    42.             theText.text += letter;
    43.             if (typeClick)
    44.                 audioSource.PlayOneShot(typeClick, 0.7F);
    45.             yield return 0;
    46.             yield return new WaitForSeconds (letterPause);
    47.         }
    48.     }
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    For good practice, it's best to cache the pause so:
    Code (csharp):
    1.  
    2. WaitForSeconds letterPause = new WaitForSeconds(.2f);
    3.  
    Also a yield return null doesn't create as much garbage as a yield return 0.

    Probably not what's slowing it down, but it's good practice to save garbage collecting.
    I also don't understand why you have two yield returns together like that.
     
  3. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Just want to add, check to make sure nothing is changing letterPause- make it protected and [SerializeField] attribute, preferably, to be absolutely certain it's only changable in the inspector or within this script. If you take Fireside's advice and cache it, that'll also work. Also, try using WaitForSecondsRealtime to be certain that the game time isn't being scaled elsewhere in the project and slowing it down that way.

    If neither of those help, then you likely just have a performance problem and it's slowing down because all updates are slowing down- or at least, that's all I can think of.
     
    KnightRiderGuy likes this.
  4. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    514
    Thanks Guys,
    I can see a performance issue being a good part of the problem because I know we have a lot of memory leaks we are still trying to track down and fix... but here is something weird I discovered yesterday.
    I moved my text object over to the main screen instead of screen two and it works fine???
    really can't figure that out,?? again the method by which it's being accessed is exactly the same as if it was on screen two... but put it on screen one and it works fine.

    I'll have to try what @fire7side suggested and see if that makes a difference. to answer his question about the double wait for seconds.... that I'm not sure, This was originally a code tutorial I followed on YouTube that I heavily modified to use UI text instead of GUI text and to draw the information from external .txt documents instead of just what was typed into the text objects type box in the inspector.... so I made a lot of heavy modifications... although not seen in this code snippet I also had added an image placeholder that simply changes the image depending on which "Factoid" has been requested so that way each information call will display a different image and then also type out the text.... took a fair amount of trial and error to get it working the way I wanted in just the separate test project.
    but yeah.... migrate it into the main project and on screen two the text type slows down but throw it onto screen one and it work fine??
     
  5. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    514
    @fire7side as an experiment I tried changing this but it just types out at a constant speed no matter what I change the value too?

    Code (CSharp):
    1. IEnumerator TypeText ()
    2.     {
    3.         yield return new WaitForSeconds (4.5f);    // Wait Time
    4.         foreach (char letter in message.ToCharArray())
    5.  
    6.         {
    7.             theText.text += letter;
    8.             if (typeClick)
    9.                 audioSource.PlayOneShot(typeClick, 0.7F);
    10.             yield return 0;
    11.             //yield return new WaitForSeconds (letterPause);
    12.             WaitForSeconds letterPause = new WaitForSeconds(0.08f);
    13.         }
    14.     }
     
  6. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    The wait time is determined by what you yield by- you're not actually yielding the new letterPause value. And he meant cache it as a class field.
    Code (CSharp):
    1. public float letterPause = .08f;
    2.  
    3. private WaitForSeconds initialWaitTime;
    4. private WaitForSeconds pauseWaitTime;
    5.  
    6. private void Awake()
    7. {
    8.     initialWaitTime = new WaitForSeconds(0.5f);
    9.     pauseWaitTime = new WaitForSeconds(letterPause);
    10. }
    11.  
    12. private IEnumerator TypeText ()
    13. {
    14.     yield return initialWaitTime;
    15.     foreach (char letter in message.ToCharArray())
    16.     {
    17.         theText.text += letter;
    18.         if (typeClick)
    19.             audioSource.PlayOneShot(typeClick, 0.7F);
    20.  
    21.         yield return pauseWaitTime;
    22.     }
    23. }
    ... or something like that.
     
    KnightRiderGuy likes this.
  7. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,383
    This is telling it to wait a whole frame, then wait the delay time. A coroutine will only fire once per frame so you will always be waiting at least two frames per character with your code there. The waitforseconds yield could be zero, but it will always be at least one frame.

    There's a lot you can do to condense it, but I don't know what is causing your delay. I wrote one and it seems to work fine.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class AutoType : MonoBehaviour
    7. {
    8.     public Text TargetText;
    9.     public AudioSource AudioSourceComp;
    10.     public AudioClip ClickNoise;
    11.     public bool SoundOnEachLetter;
    12.     public float PauseTime = 0.5f;
    13.  
    14.     [TextArea]
    15.     public string Message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam porta lobortis tellus eu fringilla.";
    16.  
    17.     private WaitForSeconds Waiter;
    18.  
    19.     public void Start()
    20.     {
    21.         Waiter = new WaitForSeconds(PauseTime);
    22.         StartCoroutine(TypeText(2));
    23.     }
    24.  
    25.     protected IEnumerator TypeText(float delay)
    26.     {
    27.         yield return new WaitForSeconds(delay);
    28.         TargetText.text = string.Empty;
    29.  
    30.         foreach (char letter in Message)
    31.         {
    32.             TargetText.text += letter;
    33.             if (SoundOnEachLetter && AudioSourceComp != null && ClickNoise != null) AudioSourceComp.PlayOneShot(ClickNoise);
    34.             yield return Waiter;
    35.         }
    36.     }
    37. }
     
  8. KnightRiderGuy

    KnightRiderGuy

    Joined:
    Nov 23, 2014
    Posts:
    514
    Thanks @Lysander That appears to work OK in my test project, I'll try it out in my main project.

    UPDATE: Appears to work in the main project to now.
    Thanks @Lysander
     
    Last edited: Jan 2, 2018
  9. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    Sorry I missed this, thanks Lysander. That's what I meant.