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

Typewriter effect with rich text tags in Timeline

Discussion in 'Timeline' started by CarlFat, May 5, 2022.

  1. CarlFat

    CarlFat

    Joined:
    Mar 3, 2022
    Posts:
    2
    I'm trying to make a typewriter effect for a playable behaviour in timeline. I got it to not display the rich text tags, but the problem is, the rich text tags still take up the same time as the normal text. How do I get the rich text tags to not take up time?
    Here is the recording:
    problem-clip.gif
    Here is my code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Playables;
    5. using TMPro;
    6.  
    7. public class TypewriterEffectBehaviour : PlayableBehaviour
    8. {
    9.     //public string DefaultText;
    10.     public string DefaultText;
    11.  
    12.     private string checkText;
    13.  
    14.     private bool isRichTextTag;
    15.  
    16.     // called every frame the clip is active
    17.     public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    18.     {
    19.         var textObject = playerData as TextMeshProUGUI;
    20.         if (textObject == null)
    21.             return;
    22.  
    23.         // given the current time, determine how much of the string will be displayed
    24.         var progress = (float)(playable.GetTime() / playable.GetDuration());
    25.         var subStringLength = Mathf.RoundToInt(Mathf.Clamp01(progress) * DefaultText.Length);
    26.        
    27.         checkText = DefaultText.Substring(0, subStringLength);
    28.         char[] line = checkText.ToCharArray();
    29.  
    30.          if(line[subStringLength - 1] == '<' || isRichTextTag)
    31.         {
    32.             isRichTextTag = true;
    33.             if(line[subStringLength - 1] == '>')
    34.             {
    35.                 isRichTextTag = false;
    36.             }
    37.         }
    38.         else
    39.         {
    40.             textObject.text = checkText;
    41.         }
    42.     }
    43. }
     
    forestrf likes this.
  2. akent99

    akent99

    Joined:
    Jan 14, 2018
    Posts:
    588
    I think the logic needs to be more complex than you have. You need to compute the length of the string without tags and use that instead of DefaultText.Length on line 25. Then you have to do something like write your own Substring method, a version that scans along the input string for the specified number of characters, skipping over tags ("<" .. ">") without counting them. So "a<b>cd</b>e" substring length 1 would return "a", length 2 would return "a<b>c" (the "<b>" is not counted), length 3 would return "a<b>cd", 4 would return "a<b>cd</b>e".
     
    CarlFat likes this.
  3. CarlFat

    CarlFat

    Joined:
    Mar 3, 2022
    Posts:
    2
    Got it. Thank you so much!
     
  4. DanielDouglas

    DanielDouglas

    Joined:
    Mar 21, 2020
    Posts:
    4
    i solve with this


    IEnumerator TypeWriterEffect(string sentence)
    {
    for(int i = 0; i < sentence.Length; i++)
    {
    if (sentence == '<')
    {
    dialogText.text += GetCompleteRichTextTag(ref i);
    }
    else
    {
    dialogText.text+= sentence;
    }
    yield return new WaitForSeconds(typingSpeed);
    }
    }
    private string GetCompleteRichTextTag(ref int index)
    {
    string completTag = string.Empty;
    while(index < currentMessages[activeMessage].message.Length) //string sentence to show.length
    {
    completTag += currentMessages[activeMessage].message[index];

    if (currentMessages[activeMessage].message[index] == '>')
    {
    return completTag;

    }
    index++;
    }
    return string.Empty;
    }



    i found the solution here in youtube video
     
    linh60bpm likes this.