Page 1 of 1

Text Mesh pro Typewriter effect

Posted: Mon Jan 07, 2019 7:12 am
by Japtor
Hi,

I have two things. One is doubt and the other is a problem.

Context: I am creating a simple introduction scene. A background image and a TextMeshPro Text with a Text Mesh pro Typewriter effect. It will write little by little a simple text and, once finished, go the first playable scene. (To make sure, I am not using a Standard Dialogue UI, etc here as I guess it is not necessary for this case).

The problem: I am using the Full Pause Duration which pauses the typewriter effect when it founds a "\." inside the text. If I write it directly inside the Text Mesh Pro UGUI (Script) -> Text Input Box something like "Hello.\. My name is Gabriel." The result is what I expected, where the "\." doesn't appear in "play mode" and pauses the time I assigned. The problem is when I use a Localize Text Mesh Pro. It seems to write also "\." in "play mode". It affects the other special characters that are mentioned inside the documentation too: "\,", >, etc. I am not really sure why.

The doubt: Is there a way to detect when it reaches a certain part of the text? I will like to make appear like a "continue button" in those moments while the Text Mesh pro Typewriter effect is paused. When the player presses it, the text continues.

Thanks! :)

Re: Text Mesh pro Typewriter effect

Posted: Mon Jan 07, 2019 10:20 am
by Tony Li
Hi Javier,
Japtor wrote: Mon Jan 07, 2019 7:12 amThe problem: I am using the Full Pause Duration which pauses the typewriter effect when it founds a "\." inside the text. If I write it directly inside the Text Mesh Pro UGUI (Script) -> Text Input Box something like "Hello.\. My name is Gabriel." The result is what I expected, where the "\." doesn't appear in "play mode" and pauses the time I assigned. The problem is when I use a Localize Text Mesh Pro. It seems to write also "\." in "play mode". It affects the other special characters that are mentioned inside the documentation too: "\,", >, etc. I am not really sure why.
Try using a Localize UI component instead of Localize Text Mesh Pro.

TextMesh Pro requires an extra frame to initialize its content. Untick the typewriter effect''s Play On Enable, and add a script like this to start the effect:

StartTMPTypewriter.cs

Code: Select all

using System.Collections;
using UnityEngine;

public class StartTMPTypewriter : MonoBehaviour 
{
    private IEnumerator Start()
    {
        var tmp = GetComponent<TMPro.TextMeshProUGUI>();
        if (tmp == null) yield break;
        var originalColor = tmp.color;
        tmp.color = new Color(0, 0, 0, 0);
        yield return null;
        yield return new WaitForEndOfFrame(); // Give TMP time to build its mesh.
        tmp.color = originalColor;
        GetComponent<PixelCrushers.DialogueSystem.TextMeshProTypewriterEffect>().StartTyping(tmp.text);
    }
}
Japtor wrote: Mon Jan 07, 2019 7:12 amThe doubt: Is there a way to detect when it reaches a certain part of the text? I will like to make appear like a "continue button" in those moments while the Text Mesh pro Typewriter effect is paused. When the player presses it, the text continues.
Assign a method to the typewriter effect's OnCharacter() event. The effect will call this method every time it adds a character. When it gets to the part where you want to stop, call the typewriter effect's Pause() method. After the player clicks the continue button, call the Unpause() method.

Re: Text Mesh pro Typewriter effect

Posted: Mon Jan 07, 2019 12:43 pm
by Japtor
Hi Tony,

Thanks for the reply!

Another doubt: I am not sure how to configure the OnCharacter() Event. How do you know when the text has arrived at the part you want to start a Pause()?

Thanks! :)

Re: Text Mesh pro Typewriter effect

Posted: Mon Jan 07, 2019 1:08 pm
by Tony Li
Check the TextMeshProUGUI's text property. Your script could check for a specific length. Here's a simple example:

Code: Select all

public class TypewriterContinueButton : MonoBehaviour
{
    public int pausedAtLength = 20; // Set in inspector.
    public Button continueButton; // Set in inspector.
    
    private TextMeshProTypewriterEffect typewriter;
    private TextMeshProUGUI tmp;
    
    void Start()
    {
        tmp = GetComponent<TextMeshProUGUI>();
        typewriter = GetComponent<TextMeshProTypewriterEffect>();
        typewriter.onCharacter.AddListener(CheckLength);        
        continueButton.onClick.AddListener(Continue);
        continueButton.gameObject.SetActive(false);        
    }
    
    void CheckLength()
    {
        if (tmp.text.Length == pausedAtLength)
        {
            typewriter.Pause();
            continueButton.gameObject.SetActive(true);
        }
    }
    
    void Continue()
    {
        typewriter.Unpause();
        continueButton.gameObject.SetActive(false);
    }
}[code]

The example above hooks up the UnityEvents in code, but you could hook them up in the inspector instead if you prefer. I just typed this script into the reply. It might have typos. I also didn't include the "using" part at the top of the script.

Re: Text Mesh pro Typewriter effect

Posted: Tue Jan 08, 2019 6:13 am
by Japtor
Hi Tony,

Thanks for the reply!

Is there not a better way than checking the length? Because when the text is in a different language, the length of the text changes.

I was thinking of using the Full Pause Duration (\.) from the Text Mesh Pro Typewriter Effect. However, I think the Full Pause Duration doesn't have able a way to pause it forever (until you know, the continue button) and also the ability to unpause it, right? For example, I tested putting "20" inside the Full Pause Duration and then use the Unpause(). The thing is Unpause doesn't unpause the Full Pause Duration.

Any other idea?

Thanks! :)

Re: Text Mesh pro Typewriter effect

Posted: Tue Jan 08, 2019 9:22 am
by Tony Li
You could put a special code inside your text, such as:

Code: Select all

This is sentence 1. <PAUSE> This is sentence 2.
In the StartTMPTypewriter's Start method, you can look for this code, record its position, and remove it before starting the typewriter effect. Something like:

Code: Select all

    private IEnumerator Start()
    {
        var tmp = GetComponent<TMPro.TextMeshProUGUI>();
        if (tmp == null) yield break;
        
        int position = UITools.StripRPGMakerCodes(tmp.text).IndexOf("<PAUSE>");
        GetComponent<TypewriterContinueButton>().pausedAtLength = position;
        tmp.text = tmp.text.Remove("<PAUSE>");
        
        var originalColor = tmp.color;
        tmp.color = new Color(0, 0, 0, 0);
        yield return null;
        yield return new WaitForEndOfFrame(); // Give TMP time to build its mesh.
        tmp.color = originalColor;
        GetComponent<PixelCrushers.DialogueSystem.TextMeshProTypewriterEffect>().StartTyping(tmp.text);
    }

Re: Text Mesh pro Typewriter effect

Posted: Tue Jan 08, 2019 12:45 pm
by Japtor
Hi,

Thanks for the reply.

It finally worked! Thank you so much!

If someone wants to do something similar with more <PAUSE> moments inside one single text. You can add something like this:
Spoiler

Code: Select all

private bool GetAllPausePosition()
{
  int position = PixelCrushers.DialogueSystem.UITools.StripRPGMakerCodes(m_TextMeshProUGUI.text).IndexOf(m_PauseString); //m_PauseString -> <PAUSE>

  // If it finds a <PAUSE>
  if (position >= 0)
  {
    m_TextMeshProUGUI.text = m_TextMeshProUGUI.text.Remove(position, m_PauseString.Length); 
    m_PausePosition.Add(position); // Adds it to a list
    return true;
  }

  return false;
}
And inside the Start add this before the StartTyping function:
Spoiler

Code: Select all

 while (GetNextPausePosition());
Thanks again, Tony! :)

Re: Text Mesh pro Typewriter effect

Posted: Tue Jan 08, 2019 1:46 pm
by Tony Li
Happy to help! Thanks for sharing your code.