This do not require much knowledge, however, an understanding of GUI and user interfaces in general could help understanding this better.
This tutorial was created 2 years ago, the date was 23/08/2020. (DD/MM/YY)
This tutorial took 7 hours to make including 47 minutes of using Roblox Studio to make images.
As of the reimagined update, this took an additional 8 hours to remake, this includes rewriting the entire tutorial, adding new scripts, rewriting outdated scripts, getting new images, fixing grammar issues and code formatting. (Even then, I'm still not done with this tutorial even if it's perfect, because I truly care about teaching you guys about this, so I'm not going to leave this in the dumpster fire)
Last updated and checked: 05/06/2023 (DD/MM/YY)
Hello you absolute legends, my name is Mark_GoodMan and welcome to the Typewriter Effects tutorial, we are going to see what we can do to achieve this simple yet effective feature.
What is a Typewriter effect?
In other words, it's an effect that causes text on GUI to appear over a given period, instead of instantly appearing like most old games do. Here's an example:
SomeTextLabel.Text = "Hey look, it's me!"
This code will make the selected TextLabel instantly change it's current text to the said text. However, most people want to make it more immersive or make some special effects to make it look professional, or at least not making it look low-quality in some cases. This is where the Typewriter effect comes in.
First up, we are gonna insert a ScreenGui into StarterGui, and then insert a TextLabel in it. (For those who don't know, you could click on the ScreenGui and click the plus button "+" to add it)
Customize anything with the TextLabel! Use the properties to adjust how you want your TextLabel to look like, but try to resize it to fit the screen, we don't want people to zoom their eyes in if the text is too small.
Make sure TextScaled is checked, though it is optional, checking this option will automatically scale the size of the text based on a person's device resolution.
Place a Localscript inside the TextLabel, then check to make sure the setup is correct as shown below:
Everything looks good? Great, let's begin the next phase.
Begin by double-clicking on the LocalScript you inserted.
First thing first, we need to make variable for the current TextLabel.
local AnyTextName = script.Parent
Now after this, there are 2 methods to create a Typewriter effect, however, I recommend the newest method from 2023 as it's more efficient, but the old method will be kept because that's what this tutorial was originally meant to be.
#2.5: METHOD A (2020)
Now, after assigning the variable, we want to make a function, you can call the function anything you want, but I will call it AutoText for an easier understanding. We will add two assignments, object and text, they can be renamed. Make sure to end the function with an end.
local AnyTextName = script.Parent
local function AutoText(object,text)
end
Then we will use for loops to repeat checking each letter. (NOTE: the #text has to be the same as the one you named on the local function)
for i = 1,#text,1 do
The number 1 after the #text are how many letters you want to type, for example, if you put to 3, then it will type 3 letters every second depending on your task.wait(), but you rarely want that to happen to your dialogue system unless you just want to mess around, so I will leave it at number 1.
Next we want to use string.sub so it will type each letter out as listened to the numbers, the number 1 determines the start of the typing, changing this will cut some letters at the start and you can say it skipped those letters to the letters after it depends on the number, I suggest leaving it at number 1. We will want to use this on any TextLabel that the script is parented to, that's why we put it as object so you don't need to rename the name for any TextLabel with different name.
local function AutoText(object,text)
for i = 1,#text,1 do
object.Text = string.sub(text,1,i)
task.wait(0.05) -- Going below 0.05 can cause issues
end
end
Having task.wait() will effect how fast the function will type each letter 1 by 1. Then we end the "for do" statement with an end.
Now you understand how the script works, here is the full script:
local AnyTextName = script.Parent
local function AutoText(object,text)
for i = 1,#text,1 do
object.Text = string.sub(text,1,i)
task.wait(0.05) -- Going below 0.05 can cause issues
end
end
Congratulation, you learned how to make the Typewriter effect! We will move on to method B.
#2.5: METHOD B (2023)
After assigning the variable, now, we begin by making a function that can be made to allow you to do multiple Typewriter effect without copy and pasting on your script. You will need three assignments, which is object, theText, and speed, these values are self-explanatory. However, we also need to use TweenService to make it smooth!
local AnyTextName = script.Parent
local Tween = game:GetService("TweenService")
local function AutoText(object, theText, speed)
end
First, we need to put the text we want into our TextLabel as usual, it should be placed in the theText argument (first argument in this local function)
local function AutoText(object, theText, speed)
object.Text = theText
end
Now, recently Roblox introduced a new property called MaxVisibleGraphemes. It's a property to render a specific amount of text string with the given number value (think of it like making the whole text invisible when the value sets to 0, but as the number increases, more characters will become visible), with this in mind, we can use it intentionally as a Typewriter effect!
That being said, the next thing we should do is create a tween for our new text when we enter them soon. Combine the TextLabel variable, with the Tween information variable, and then the Text we want to give in the table to animate it! Don't forget to set the value of MaxVisibleGraphemes at 0 at the start each time this function fires.
One more thing, the MaxVisibleGraphemes will automatically be determined based on how many characters you wrote at theText, so you don't have to do it manually (Which is #theText, used to calculate the total amount of characters the given text has).
local function AutoText(object, theText, speed)
object.MaxVisibleGraphemes = 0 -- Pretend the text got deleted
object.Text = theText
Tween:Create(object, TweenInfo.new(speed), {MaxVisibleGraphemes = #theText}):Play()
end
Alright, it seems like everything is working, here's the full code to double-check:
local AnyTextName = script.Parent
local Tween = game:GetService("TweenService")
local function AutoText(object, theText, speed)
object.MaxVisibleGraphemes = 0 -- Pretend the text got deleted
object.Text = theText
Tween:Create(object, TweenInfo.new(speed), {MaxVisibleGraphemes = #theText}):Play()
end
Let's test out the code to confirm that it works!
Again, this will split into neither of both METHOD A and B:
#METHOD A
As previously mentioned, the object is the TextLabel your going to target, and the text is the text you want that given target to write out.
local AnyTextName = script.Parent
local function AutoText(object,text)
for i = 1,#text,1 do
object.Text = string.sub(text,1,i)
task.wait(0.05) -- Going below 0.05 can cause issues
end
end
task.wait(5) -- Load the game first or the text will finish before your eyes
AutoText(AnyTextName, "i dont know what to put here lol")
After this, you can run the game to test the code.
Now I tested it myself, and it worked, but let's see how it actually looks like. Also, make sure the GUI size fits the screen, put it on top so you can easily see it and spot the text changing.
Wow, that was an awesome magic trick right there buddy! It took ~1.43 seconds to complete animating the text "i dont know what to put here lol". Very well indeed! It looks like everything is done, congratulation!
#METHOD B
This new method has the same results as METHOD A. However, this one will animate the text more smoothly, while the text will stay in its position and doesn't move when new texts are rendered. It's also not dependent on your FPS, unlike method A.
Why don't you go try it yourself?
local AnyTextName = script.Parent
local Tween = game:GetService("TweenService")
local function AutoText(object, theText, speed)
object.MaxVisibleGraphemes = 0 -- Pretend the text got deleted
object.Text = theText
Tween:Create(object, TweenInfo.new(speed), {MaxVisibleGraphemes = #theText}):Play()
end
-- Setting "speed" to 2.5 means it takes 2.5 seconds to animate the text
while task.wait(4) do
AutoText(AnyTextName, "uhh, what am i doing here?", 2.5)
task.wait(4)
AutoText(AnyTextName, "it seems like its raining a lot here man", 2.5)
end
Now one final thing to note is that the method B that I wrote wasn't as efficient, you could use something such as the utf8 library to make a better version of Typewriter than mine, but I'm only here to show the basics.
#4. ENDING & EXTRAS:
I would like to thank you everyone for reaching the end, and for reading this tutorial.
I hope this serves you when you're making your own game, goodluck and have fun!
05/06/2023 Update log: - Added "SOUNDS ON TYPEWRITER" in extras - You can now apply Method B to any TextLabel with the "object", just like method A. - Improved Method B, MaxVisibleGraphemes is now automatically determined. - Made some explanations clearer / Rephrased some words for better understanding. - Minor grammar improvements overall.
Here are some extras to give you some more time to play around with this. I will add more soon if I can figure out some new fun stuff with this Typewriter effect.
#Both method are included, copy the ones that you need.
RANDOMIZED TYPEWRITER (Select a random text in the given table then animate it)
local RandomTextTable = {
"Hey, a random text I guess?",
"Can I have another one please? Thanks.",
"Yo, this is getting so random, uh...",
"The heck is this abomination dude?",
"Hey man, have you ever wonder why we are having randomized texts?",
"I am your best friend here to save you from hours of coding!!!",
"Final text and goodbye lol",
-- If you want to put more text, make sure to put a comma after the text ( , )
}
-- METHOD A (2020)
while task.wait(5) do
AutoText(AnyTextName, RandomTextTable[math.random(1,#RandomTextTable)])
end
-- METHOD B (2023)
while task.wait(5) do
AutoText(AnyTextName, RandomTextTable[math.random(1,#RandomTextTable)], 3)
end
SOUNDS ON TYPEWRITER (Plays a specific sound when animating the text)
-- This modified function plays a sound for each letter animated
-- ONLY USE SHORT SOUNDS THAT TYPICALLY LAST FOR <1 SECOND
-- METHOD A (2020)
local function AutoText(object,text,soundToPlay)
for i = 1,#text,1 do
object.Text = string.sub(text,1,i)
soundToPlay:Play() -- Play the selected sound
task.wait(0.05) -- Going below 0.05 can cause issues
end
end
AutoText(AnyTextName, "very noisy typewriter, dude...", --[[The sound to play]])
-- This modified function only plays a single but long sound when AutoText was called
-- If the sound duration is shorter than the "speed" of the AutoText, then check the Looped on
-- METHOD B (2023)
local function AutoText(object, theText, speed, soundToPlay)
object.MaxVisibleGraphemes = 0 -- Pretend the text got deleted lol
object.Text = theText
local Animate = Tween:Create(object, TweenInfo.new(speed), {MaxVisibleGraphemes = #theText})
Animate:Play()
local DupedSound = soundToPlay:Clone() -- Clone the sound
DupedSound.Parent = script
DupedSound:Play()
Animate.Completed:Connect(function() -- Also runs when the tween got cancelled
DupedSound:Stop() -- If completed, then we will stop the sound
end)
-- This will make sure the sound doesn't conflict with another when multiple AutoText was called
end
AutoText(AnyTextName, "yea so I heard that something is coming...", 3, --[[The sound to play]])