Typewriter Effects: 2 Methods
by: @DasKairo
This is a remake of a Topic I made back in November 22, 2022.
By Remake, I mean that I completely rewritten it. The Orginal Took at about an Hour or so to make, the rewrite took me 6 hours to do. What am I doing with my Life?
This is the Topic to I am refering to, to be exact:
I Get it, this was a Stupid thing to do, Create and entirely new Topic instead of Editing it, and I understand why, but here I wanted to add a Bit more Detail to the already existing Topic and just restart it with more Details and Decoration to it, Also, The Updates Made wont bump the Topic, and Bumping it more via Reply wouldn’t be a very good idea.
I dont really want to mess around with older Replies on the Post, Because it would just make them off topic from the Actual Topic
However, That isnt an Excuse for why I made a Completely new Topic, and you can get mad at me all you want about it.
But If you want to view the Old version, you can, But this is more of a 2.0 of it maintaining a lot of the Information, Except Probably more Detailed and Decorated.
Table Of Contents
(Broken. idk why)
Heading: | Order: |
---|---|
Topic Title | Start |
Introduction | 1 |
MaxVisibleGraphemes |
2 |
string.sub() |
3 |
Optionals | 4 |
Polls | End |
Hello!
This is just a Tutorial on how to Make a Simple Typewriting Effects on ROBLOX if you didnt know how, or you want Someone to look at for a better understanding.
This isn’t really intended to be a Advanced Tutorial, but more of a Basic, and Simple Tutorial you can use for work, or for fun. There are obviously better ways you can make typewriter effects usually involving more understanding of specific things, but for this, not really, However you are allowed to share your Creations and there is nobody stopping to you so.
Note that I may not be accurate with that I say in this Topic, Some of the Definitions of things are Simplified to help with Understanding and may be off from the Actual meaning of what it actually does (or is), So If I do make mistakes, feel free to Correct me or let me know of my mistake.
This is mostly coming from me (A very Horrible Scripter) with a Little Help of Something called Roblox Documentation.
Anyway, Back to the Topic.
When It comes to this, you may be wondering where to use it? Here is a list of Places where you can actually use this Script, and The Scripts you can use it for:
Places to use this Script: | Script Types you can use: |
---|---|
ServerScriptService |
Script |
StarterGui |
LocalScript |
About Anywhere! |
ModuleScript |
But about the "Roblox Documentation, " These are Sources from which I got this information, Along with a Model Kit I made In case you are lazy and dont like using Tutorials by other people. How Rude…
Resource: | Link: |
---|---|
string Library |
string | Roblox Creator Documentation |
MaxVisibleGraphemes |
New Property: MaxVisibleGraphemes |
Model Kit (By me!) | Typewriter Effects - Roblox |
“Beginner” Things:
When Creating a Typewriting effect, Keep in mind that the method you are doing, probably isnt the best one out there (Like this Topic), But one of the worst ways (if not “the” worst) to create a Typewriting effect would be this:
Text = "" -- starts off with an Empty String
wait(.1) -- "yields" for .1 of a Second (1/10) with throttling
Text = "H" -- Adds a Character
wait(.1)
Text = "He"
wait(.1)
Text = "Hel"
wait(.1)
Text = "Hell"
wait(.1)
Text = "Hello"
wait(.1)
Text = "Hello!" -- End Result
wait(.1)
There are many discrepancies between the Methods I’ll Cover, and This, along with many Issues. This is very inefficient to be doing and is something that a “Beginner” would do, this also relies on the usage of a Deprecated Global, A faster and more accurate yielding method than wait()
is Deprecated now, and should be Replaced with task.wait()
,wait()
, it also takes a long time to write and takes way more lines compared to the Methods We will Cover, not a good thing, its understandable that “it makes it easier to read.” but that argument isnt very good when it comes to usage, it makes your code look ugly instead of more cleaner.
With the Code in this Tutorial, It should Simplify this usage, and should be more efficient using more recent methods.
String Length:
String length (referring to the size which is the amount of characters a string
holds) is what we will be using to help use keep track of how much we need to repeat our code, this can be done with multiple functions, along with the usage of an operator, like for Example:
local myString = "Hello world!" -- we have our string here
local charCount = string.len(myString)
-- gets the Length of the string via string function
-- Method 2:
local charCount = myString:len()
-- gets the Length of the string via function for class
-- Method 3:
local charCount = #myString
-- gets the Length of the string via '#' operator
-- this would generally be the fastest method
print(charCount) --> 12 (Characters in the string including spaces)
And if you don’t want it to include spaces, you can always use string.gsub()
, like this:
local myString = "Hello world!" -- our string
local removedSpaces, charactersReplaced = string.gsub( -- gsub function
myString, -- The String you want to change
" ", -- Pattern you want to Replace
"", -- Replacement
)
print(#removedSpaces) --> 11 (Characters in the string without spaces)
print(charactersReplaced) --> 1 (Amount of Characters Changed)
These are all Correct, but they arent all the same, and others are more efficient than others, #
is the likely choice due to its simplicity and its speed, it can also be used to check the number of items in a table, like so:
t = {"Apples"} -- table (this type is known as an 'Array')
print(#t) --> 1
-- ("Apples" is inside the Table, if it wasnt, it would be 0)
However, this table
Example is not Important or Relevant to the Heading, so I’ll Continue.
Function Usage:
For the Purpose of us not repeating our code and having to rewrite them everytime we want to use them, we can use functions
for this, so they are reusable for us.
This however, you should already know this.
opening keyword | closing keyword |
---|---|
function |
end |
function func()
end
-- Alternate Method:
local func = function()
end
Loop Usage:
We use a little something known as Loops to help us with repeating code, As of Currently we have 3 types of loops:
Loop keyword | Closing keyword |
---|---|
while |
end |
repeat |
until |
for |
end |
So Instead of us constantly writing the exact same line for a certain amount of times, we can utilize these to our advantage, here is how you set them up:
while Condition do -- while a condition is true, it will repeat
end
repeat
until Condition -- repeats until a condition is false
for i = 1,10 do -- repeats a certain amount of times
end
for index, value in Array do -- repeats for how many items are within a table
end
It is best to note that these loops will yield until they are broken with the usage of the break
method, however now we have to set the speed we want our loop to go, which we have to apply ourselves, if we dont do this, our game will crash completely, and cause a timeout, which isnt what the want with our code, so in order to prevent this, we will use task.wait()
to yield how times our loop will go through.
while Condition do
task.wait(.1) -- yields .1 seconds before Moving to the next Iteration
end
Now, you may be wondering: What Is an Iteration?
An Iteration in simple terms is A Sequence of code that is repeated until a specific result is acheived. Which will help us with our Typewriter effect.
MaxVisibleGraphemes
purpose is intended for the usage of Typewriting effects. So It wouldn’t make sense that we wouln’t have it here,.So for this, I will show you how to make the Typewriting effect for this Tutorial,.
We First Start off with either a TextLabel
or a TextButton
here, With these Instances
, we can use them to typewrite text onto them using their Text
Property, you can either Assign a Variable to an Already Existing Instance
or you can create a brand new one using Instance.new()
, For the Tutorial However, it will be known as Frame
.
We will also be using a function
to store our code, like this:
local function Typewrite(str: string, speed: number)
-- 'str' is our string we will be typewriting
-- 'speed' is the speed per each addition
-- Keep Reading, you're almost there!
end
This is help us reuse the function whenever we want to use instead of having to write it al over again, which isn’t good practice.
The Second Thing we will do here is Apply our Text, which is as simple as you think, you can use the Text
property of your TextLabel
or TextButton
to have text within them, so within our function, we can Apply it as such:
Frame.Text = str -- Applies our string to the Frame
Keep in mind that it will not work if you do this:
local text = Frame.Text -- string
text = str -- string
What this is doing is returning text for our Variable, and we are only changing our Variable to another , which isn’t what we want, we want to apply to a Property, not get the Value of a Property, if that makes sense.string
The Second Property we will be Modifying is the MaxVisibleGraphemes
Property, which basically is how many characters are visible at a time, by Default, it will be set to -1
which makes all the Characters within the Frame Visible at once.
So if we set this Property to 0
, It will show 0
characters, don’t get scared about that, you are following this Tutorial very well, So now if we set this Property to 1
, It will now show one character, so you can think of it like this:
------------------------------------------------------------------------------
-- Original Properties of our Text
OriginalText = "Hello!"
#OriginalText --> 6 (6 Characters Total)
------------------------------------------------------------------------------
-- How Its Rendered by TextLabel / TextButton
RenderedText = " " -- MaxVisibleGraphemes = 0 (0/6 Characters)
RenderedText = "H " -- MaxVisibleGraphemes = 1 (1/6 Characters)
RenderedText = "He " -- MaxVisibleGraphemes = 2 (2/6 Characters)
RenderedText = "Hel " -- MaxVisibleGraphemes = 3 (3/6 Characters)
RenderedText = "Hell " -- MaxVisibleGraphemes = 4 (4/6 Characters)
RenderedText = "Hello " -- MaxVisibleGraphemes = 5 (5/6 Characters)
RenderedText = "Hello!" -- MaxVisibleGraphemes = 6 (6/6 Characters)
Now if you add one more to MaxVisibleGraphemes
, which would be 7
, it would render anymore Text as there is no more to Render until you add more text, if you want the same text to repeat, you can use string.rep
or concatenate the Variable to Itself.
Obviously, as you can tell this isn’t a very good Example for MaxVisibleGraphemes
, nor what It actually is, its more of for you to play with the Actual Properties so you can get a Better Understanding of them, But it would get the job done for explaining “Invisible Text”, but anyway:
We now have a Understanding on what MaxVisibleGraphemes
is, Goob Job!
With this new Knowledge, we can know Apply it to our Script, Like so:
local function Typewrite(str: string, speed: number)
Frame.Text = str -- Applies string for usage
Frame.MaxVisibleGraphemes = 0 -- Sets Visible Characters to 0
-- There is still more to come :)
end
So now, we have about half of our Script done, We now need to loop through how many times for how big the text is, yep you guessed it.
For the Third thing, we will now get the Length of the String using the #
operator, which will return as 6
according to the number of characters in our string; Hello!
, so how will this help us? from here we will use a loop known as a for
loop to keep track of the amount of iterations we will do, so with the loop, we will write this inside the function:
for i = 1, #str do -- this will repeat for the amount of characters within the string
-- code in a sec
end
So here, we will now add 1
to MaxVisibleGraphemes
so for each iteration, there would be 2 ways you can do the following
MaxVisibleGraphemes = MaxVisibleGraphemes + 1 -- if we have 0, it would be 0 + 1 which is 1
MaxVisibleGraphemes += 1 -- Simplified version
Frame.MaxVisibleGraphemes = i
-- Adds Graphemes (Characters) based on how many times the for loop ran
The i
method requires the usage of the for
loop as we have it set there, since we have it as 1
, out of 10
, it will continue to add up per iteration until it reaches the expected number (which is 10
) which is what the i = 1,10
part of the loop does, or it breaks with the usage of break
, keep in mind continue
doesnt actually break the loop, it skips the iteration its in, if you are on point 1, it will skip to point 2.
So now If we integrate this chunk of code into out code, it will look like this:
local function Typewrite(str: string, speed: number)
Frame.Text = str
Frame.MaxVisibleGraphemes = 0
for i = 1, #str do -- for loop
Frame.MaxVisibleGraphemes += 1 -- Adds Graphemes (Characters)
end
end
The Next- Oh… We forgot a very Important thing, Always remember to add If you have a very long task.wait()
when using a for loop.string
, It will run this code so many times causing the game to crash, or cause a time out within the code, with task.wait()
, we can prevent this from happening, so this is what it will look like:
for i = 1, #str do
Frame.MaxVisibleGraphemes += 1
task.wait(speed) -- this is where the 'speed' variable comes in
end
So, with that out of the way, you can now Test the code, Which this should be the full code:
local function Typewrite(str: string, speed: number)
Frame.Text = str -- Applies string for usage
Frame.MaxVisibleGraphemes = 0 -- Sets Visible Characters to 0
for i = 1, #str do -- this will repeat for the amount of characters within the string
Frame.MaxVisibleGraphemes += 1 -- Adds Graphemes (Characters)
task.wait(speed) -- yields with the speed given
end
end
So Basically now, you can write this using the function:
Typewrite("This is a Typewrite Effect!", .1)
-- "This is a Typewrite Effect!" is the string to be used
-- .1 is the amount of time the code will yield per iteration
Which Should Be all for the MaxVisibleGraphemes
version of the Tutorial
For the Purpose of the string.sub()
, You can follow the MaxVisibleGraphemes
as it would be very Similar to this, This will Mainly be Modifying the MaxVisibleGraphemes
Version of the code, remember this is also slighly more “Advanced” than MaxVisibleGraphemes
, so sorry if I make this confusing.
From the Last Tutorial, We have this code;
local function Typewrite(str: string, speed: number)
Frame.Text = str -- Applies string for usage
Frame.MaxVisibleGraphemes = 0 -- Sets Visible Characters to 0
for i = 1, #str do -- this will repeat for the amount of characters within the string
Frame.MaxVisibleGraphemes += 1 -- Adds Graphemes (Characters)
task.wait(speed) -- yields with the speed given
end
end
Now, What do you do with this? Well, here I will show you how to Modify the Code
First thing we would do is Swap out MaxVisibleGraphemes
with string.sub()
, But now, We must know the Arguments, there are 3 of them to be Exact:
s
is the string
you are using, which in our Example, would just be Hello!
i
is the Amount you want to start at, The Default is at 1
which is the first Character of the string
j
is the Amount you want to end at, The Default is -1
which would be the last Character of the string
But, when we set j
to 0
, it will be invisible, and if we set j
to 1
, it will only show the first character, and so on.
So knowing this, within the code we can use the for
loop to have i
continue until j
, which in this case, i
in our for
loop (which keeps tracks of the iterations) can be used to have the i
Argument continue to that number, so for this purpose, I will name i
within the for
loop, index
so you can define it:
for index = 1, #str do -- this will repeat for the amount of characters within the string
Frame.Text = string.sub(str, 1, index) -- Adds Characters until it reaches index
-- so if it ran 3 times, it will show 3 Characters because 'index' is equal to 3
task.wait(speed) -- yields with the speed given
end
So now, you dont need to Apply the Text Early, you can instead use string.sub
to apply the substring of the string
, This should be the full code:
local function Typewrite(str: string, speed: number)
for index = 1, #str do -- this will repeat for the amount of characters within the string
Frame.Text = string.sub(str, 1, index) -- Adds Characters until it reaches index
-- so if it ran 3 times, it will show 3 Characters because 'index' is equal to 3
task.wait(speed) -- yields with the speed given
end
end
So now, you can test the Code how you tested with MaxVisibleGraphemes
which should Be the Exact same thing:
Typewrite("This is a Typewrite Effect!", .1)
-- "This is a Typewrite Effect!" is the string to be used
-- .1 is the amount of time the code will yield per iteration
And I believe that should be all for string.sub()
There are some Optional Things you can do to the code, Keep in mind that these may cause Issues with your code depending on how you handle them.
Note that The code blocks are all Example code, not the Actually code, as for an Example.
Preventing Yielding
If you ever want to prevent yielding, you can use coroutines or task for this purpose, this would have the code run alongside the Main Code using threads
, which would prevent yielding from the code, The only yielding that will happen is the code within the thread
, but it shouldn’t cause issues.
If you have the same function run right after, It may cause the Issue of two Typewriting Effects Happening at the Same time, which would not look great.
Setting Default Values
Within your code, you can set Default values of items, so when you dont add a Argument inside the function
, you can simply say to give another value instead:
function ex(x: number)
print(x or 1) -- if x is nil (no value given) it will print "1" instead
end)
ex(2) --> 2 (value given)
ex() --> 1 (no value given)
ex(nil) --> 1 (no value given)
Ending functions and or returning Data
You can end a function early if a condition isnt met, or to return a piece of Data, Like this:
-- 'return' ends a function early, but can return Data
function ex(x, y)
local random = math.random(x, y)
if random ~= 1 then
return false -- returns a boolean
end
-- if statement can be simplified to:
return (random == 1) -- returns a Boolean
end
local byChance = ex(1, 10) -- Variable Assigned to returned Data
if byChance then -- if true
print"got 1 by chance!"
end
Polls
If you want, you can Answer these, These are just what you think, They are very much Optional.
- Useful
- Good
- Ok
- Bad
- Terrible
0 voters
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
0 voters
If you think It’s Bad, You can always say why!