Last active
January 9, 2021 16:07
-
-
Save brihernandez/4c1e28ddb0599628810d597668894bfd to your computer and use it in GitHub Desktop.
Extension method to reveal TextMeshPro characters over time. Requires UniTask.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Threading; | |
using Cysharp.Threading.Tasks; | |
using TMPro; | |
public static class TextMeshProExtensions | |
{ | |
private static Dictionary<TextMeshProUGUI, CancellationTokenSource> textToCancel = new Dictionary<TextMeshProUGUI, CancellationTokenSource>(); | |
/// <summary> | |
/// Reveals characters of the given text with a delay between each character. | |
/// </summary> | |
/// <param name="milliseconds">Milliseconds between each character being shown.</param> | |
/// <param name="padding">Adds this to the number of characters to be revealed. Can be used if the text might | |
/// change while the reveal is happening to make sure all the characters are available.</param> | |
/// <example> | |
/// yourTMProText.RevealTextWithDelay(20).Forget(); | |
/// </example> | |
public static async UniTaskVoid RevealTextWithDelay(this TextMeshProUGUI proText, int milliseconds = 10, int padding = 0) | |
{ | |
// If this text is already in the middle of revealing text, cancel its currently running | |
// task so that the reveal process can be restarted. | |
if (textToCancel.ContainsKey(proText)) | |
{ | |
textToCancel[proText].Cancel(); | |
textToCancel.Remove(proText); | |
} | |
// Create a cancellation token that can be called to interrupt this text in case it's told | |
// to reveal text while in the middle of already revealing it. Combo it with the typical | |
// Unity OnDestroy token to handle the usual case of the object disappearing while running. | |
var interruptShowingTextCancel = new CancellationTokenSource(); | |
var superCancel = CancellationTokenSource.CreateLinkedTokenSource( | |
interruptShowingTextCancel.Token, | |
proText.GetCancellationTokenOnDestroy()); | |
textToCancel.Add(proText, superCancel); | |
var lastUpdateTime = System.DateTime.Now; | |
int visibleCount = 0; | |
while (visibleCount < proText.text.Length + padding) | |
{ | |
// Since frame times can be longer than the number of milliseconds desired between | |
// characters, account for how many letters would have passed since last cycle. | |
var timeSinceLast = System.DateTime.Now.Subtract(lastUpdateTime); | |
int extraCharacters = timeSinceLast.Milliseconds / milliseconds; | |
visibleCount += 1 + extraCharacters; | |
proText.maxVisibleCharacters = visibleCount; | |
lastUpdateTime = System.DateTime.Now; | |
await UniTask.Delay(milliseconds, cancellationToken: superCancel.Token); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment