Typewriter: Create awesome typewriter effects!

Hey everyone! I’ve just finished a cool module which will let you make these SICK typewriter effects:

PLEASE NOTE: this an effect, the user isn’t typing anything in-game

This can be used for story games, maybe tutorials, etc.

Get the module here: https://www.roblox.com/library/7353187164/Typewriter-MODULE

Before you start:

Make sure all the objects have their AnchorPoint set to 0.5,0.5

Tutorial

Step 1: provide your objects

local TypeWriter: ModuleScript = require(game:GetService("ReplicatedStorage"):WaitForChild("Typewriter"))

local object = TypeWriter:CreateTypeWriterObject(TextLabel, Cursor)

Step 2: Typing Text

Have your text array at the ready! Not required, but it will be useful. Additionally, make sure to have LetterDelay variable defined in order for the script to know how much yield each letter should have.

local TypeWriter: ModuleScript = require(game:GetService("ReplicatedStorage"):WaitForChild("Typewriter"))

local StringTable: {any} = {
	[1] = "Hey!",
	[2] = "I am alexfinger21,",
	[3] = "welcome to this tutorial!"
}

local object = TypeWriter:CreateTypeWriterObject(TextLabel, Cursor)

object.LetterDelay = 0.09

object:Type(StringTable[1])

Step 3: Deleting text:

The argument for this one is the number of characters you would like to delete.

local TypeWriter: ModuleScript = require(game:GetService("ReplicatedStorage"):WaitForChild("Typewriter"))

local StringTable: {any} = {
	[1] = "Hey!",
	[2] = "I am alexfinger21,",
	[3] = "welcome to this tutorial!"
}

local object = TypeWriter:CreateTypeWriterObject(TextLabel, Cursor)

object.LetterDelay = 0.09

object:Type(StringTable[1])

wait(0.5)

object:Delete(4)

You’re done!

Documentation

object =TypeWriter:CreateTypeWriterObject(TextLabel, Cursor)
Creates an object which you will use to control the typewriter.

object.LetterDelay = num
The yield of each letter

object:Type(string)
Will procedurally type a string on the TextLabel

object:Delete(number)
Amount of chars it will delete, from right to left.

Important: every function, such as :Type and :Delete yields, so keep that in mind.

Source Code

local typeWriter: {any} = {}
typeWriter.__index = typeWriter
local transparency = 1

function typeWriter:CreateTypeWriterObject(TextObject: TextLabel?, Cursor: ImageLabel?)
	local newTypeWriter: {any} = {}

	newTypeWriter.Cursor = Cursor
	newTypeWriter.TextObject = TextObject

	if not Cursor then
		local clone = script.Cursor:Clone()
		clone.Parent = TextObject.Parent
		newTypeWriter.Cursor = clone
	end

	setmetatable(newTypeWriter, typeWriter)

	task.spawn(function()
		while Cursor do
			local tween: Tween = game:GetService("TweenService"):Create(Cursor, TweenInfo.new(0.2, Enum.EasingStyle.Cubic, Enum.EasingDirection.InOut), {ImageTransparency = transparency})
			tween:Play()
			transparency = transparency == 1 and 0 or 1
			tween.Completed:Wait()
			wait(0.2)
		end
	end)

	return(newTypeWriter)
end

function typeWriter:Type(textString: string)
	assert(textString, "You haven't provided any string text!")

	local originalText = self.TextObject.Text

	for char = 1,string.len(textString),1 do
		local text = string.sub(textString, 1, char)
		self.TextObject.Text = originalText .. text
		self.Cursor.Position = self.TextObject.Position + UDim2.fromOffset(self.TextObject.TextBounds.X/1.95, 0)

		wait(self.LetterDelay)
	end

	return true
end

function typeWriter:Delete(numChars: number)
	assert(numChars, "You haven't provided a valid number argument!")

	for i = string.len(self.TextObject.Text),string.len(self.TextObject.Text)-(numChars+1),-1 do
		local text = string.sub(self.TextObject.Text, 1, i)
		self.TextObject.Text = text
		self.Cursor.Position = self.TextObject.Position + UDim2.fromOffset(self.TextObject.TextBounds.X/1.95, 0)

		wait(self.LetterDelay)
	end
end

return typeWriter

Example Script (used in the video):

local plr: Player = game.Players.LocalPlayer

local parent: ScreenGui = script.Parent

local TextLabel: TextLabel = parent:WaitForChild("Object")

local Cursor: TextLabel = parent:WaitForChild("Cursor")

local TypeWriter: ModuleScript = require(game:GetService("ReplicatedStorage"):WaitForChild("Typewriter"))

local StringTable: {any} = {

[1] = "Hey!",

[2] = "I am alexfinger21,",

[3] = "welcome to this tutorial!"

}

local object = TypeWriter:CreateTypeWriterObject(TextLabel, Cursor)

wait(2)

object.LetterDelay = 0.09

wait(0.5)

object:Type(StringTable[1])

wait(0.5)

object:Delete(4)

wait(0.5)

object:Type(StringTable[2])

wait(0.5)

object:Delete(12)

wait(0.7)

object:Type("PRO")

Hope you enjoyed it, please comment any recommendations below!

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

0 voters

15 Likes

Is there really a need for that, though? I don’t really need that since my module works a bit differently.

1 Like

That’s the troll person who attacked me on my post too!

I think your project is very cool and help a lot of new scripters, great job, friend! :blue_heart: I hope to see some more of your epix projects, don’t loose motivation just because this hateful person is going around on other’s posts!

:smile:

3 Likes

If I may make a suggestion: use the utf8 library, not the string library. String only considers individual bytes while utf8 can handle UTF-8 encoding. One issue you might encounter while using this module is typewriting emojis or foreign characters (e.g. languages with logographic characters).

Roblox also has a built-in way to typewrite, MaxVisibleGraphemes, if you just need characters to appear and don’t do any special typewriting effects. You can count the total number of graphemes, set this to 0 and increment it up until MaxVisibleGraphemes matches your counted graphemes.

2 Likes

i have a suggestion,you could add a something like TypeWriter.Completed event which fires when the TypeWrite:Type() finishes

1 Like

Sure, I will do that tomorrow!

1 Like

Ok, thanks so much, I’ll make sure to fix that!

I’d really recommend doing task.wait() instead of wait(). It’s an improved version soo.

But overall, it’s probably one of my favorite modules so far.

2 Likes

Alright, will make sure to fix!