An efficient, robust, open-source text rendering module for
Roblox, featuring custom fonts and advanced text control.
More creativity!
Roblox developers suffer from a wide range of limitations.
This module aims to fix text limitations, allowing more
developers to unleash their creativity with text.
What it really does:
- Custom fonts: Use any font file, whether completely custom or one found online.
-
Advanced control:
- Easily transform and style any individual character, word or line.
- Utilize awesome text styling like ‘justified’ alignments and spacing controls.
Check it out below!
🎬 Showcases
Dialogue
A really simple ‘dialogue’, featuring:
- Custom font.
- Text appear and disappear animation.
- ‘Shining’ word animation.
Text explosion
A neat text explosion effect.
Features a custom font too.
Efficient, robust, intuitive.
- Blazingly fast speeds.
- Clear error feedback.
- Typing & documentation.
Learn how to use it!
🚀 Fundamentals
Getting the module
Let’s first get the module. There are two ways:
-
Get it from the creator store:
- Click
Get
at the top of this post. - Click
Get Model
on the store. - Open the ToolBox in Roblox Studio.
- Go to the
Inventory
tab. - Click on
Text+
.
- Click
-
Get it from GitHub:
- Click
Git
at the top of this post. - Go to
Releases
. - Download the latest
.rbxm
file. - Find the file in your file explorer.
- Drag the file into Roblox Studio.
- Click
Find a great place for the module in your explorer.
Basics
You’ll be creating text using frames as parents and boundaries, like this:
local textPlus = require(script.TextPlus)
local frame = path.to.frame -- You should actually get or create a frame.
textPlus.Create(
frame, -- Parent and boundary.
"This text is awesome!", -- Text.
)
The text will be wrapped inside of the frame.
Note that it will ignore any UIPadding.
You can get the text at any time like this:
textPlus.GetText(frame) -- Will return a string.
Line breaks
You can manually break lines by using multiline strings.
There are two ways to do this.
Use \n
You can use \n
to break to the next line at any place.
\n
will not be shown in the text.
"First line\nSecond line"
Use multiline strings
Using [[]]
instead of ""
will allow you to create a string that takes up multiple lines.
You simply make an actual line break, and it will work.
[[First line
Second line]]
Customization
The customization works with a table, where you can provide any customizations you want.
You don’t have to provide all, or even any, because they all have defaults.
You use it like this:
textPlus.Create(
frame, -- Parent and boundary.
"This text is awesome!", -- Text.
{ -- Customization (optional).
Size = 24,
Color = Color3.fromRGB(255, 255, 255),
XAlignment = Enum.TextXAlignment.Center,
YAlignment = Enum.TextYAlignment.Center,
}
)
Full list of customization options:
- Size: number
- Font: Font | CustomFont
- Color: Color3
- Transparency: number
- Rotation: number
-
Offset: Vector2
- StrokeSize: number
-
StrokeColor: Color3
- ShadowOffset: Vector2
-
ShadowColor: Color3
- LineHeight: number
-
CharacterSpacing: number
-
Truncate: “Tail” | “Break”
- XAlignment: “Left” | “Center” | “Right” | “Justified”
-
YAlignment: “Top” | “Center” | “Bottom” | “Justified”
- WordSorting: boolean
-
LineSorting: boolean
- Dynamic: boolean
You can get the customization for a frame at any time like this:
textPlus.GetCustomization(frame) -- Will return a table.
This customization will always be valid, and will contain all customization options except false
booleans and a select few customizations that are not required in the list.
Fonts
The font is one of the customization options, and works mostly like all of the others.
It takes in either:
- A
Font
object, usually created withFont.new()
. - A custom font table. Refer to the
Custom Fonts
tutorial section.
You can use it like this:
textPlus.Create(
frame,
"This text is awesome!",
{
Font = Font.new(
"rbxasset://fonts/families/Arial.json", -- Family.
Enum.FontWeight.Regular, -- Weight.
Enum.FontStyle.Normal -- Style.
)
}
)
Built-in fonts
You can find a lot of fonts on the documentation page.
Simply copy the asset id from the font list and paste it into the Font
object’s Family
(first argument).
Creator store fonts
Alternatively, browse many more fonts at the creator store.
Click Get Font
.
Create a TextLabel
in Roblox Studio and apply the font to it.
Make sure you have the TextLabel selected and run this in the command bar:
print(game.Selection:Get()[1].FontFace.Family)
It will output the asset id, that you need.
Simply copy and paste it into the Font
object’s Family
(first argument).
Custom fonts
If it’s still not enough, custom fonts offer endless possibilities.
But that has it’s own section (also in this post). Consider checking it out.
Modification
You can also modify a text frame after the creation. It’s done the same you create it to begin with:
textPlus.Create(
frame, -- Frame that already has text created within it.
"This text has been modified!" -- New text.
)
You can even modify the customization after the creation like this:
textPlus.Create(
frame, -- Frame that already has text created within it.
"This text has been modified!", -- New text.
{ -- New customization (optional).
Size = 12 -- Overwrite size.
-- Everything else will stay like before!
}
)
It will keep all previous customization options, only overwriting with those you provide in the table.
Text bounds
It will automatically calculate the text bounds when you create text.
You can always get the text bounds of a frame like this:
textPlus.GetTextBounds(frame) -- Will return a Vector2.
⚙️ Fine-control
Introduction
The sorting options in the customization are crucial to fine-control.
Using word and line sorting, you can not only modify individual characters, but whole words and lines.
Use the sorting customization options like this:
textPlus.Create(
"Text",
frame,
{
LineSorting = true,
WordSorting = true
}
)
By default, line and word sorting will both be off, meaning your frame will contain pure characters.
Note that everything is named numerically, relative to its parent.
Both lines and words will be sorted using folders:
(Both sortings enabled)
Full looping
It’s pretty simple to loop through. Just make sure you respect your sorting.
Here’s an example with both sortings enabled:
for lineNumber, line in frame:GetChildren() do
print("Line "..lineNumber) -- "Line 1", "Line 2" etc.
-- 'line' will be a folder.
for wordNumber, word in line:GetChildren() do
print("Word "..wordNumber) -- "Word 1", "Word 2" etc.
-- 'word' will be a folder.
for characterNumber, character in word:GetChildren() do
print("Character "..characterNumber) -- "Character 1", "Character 2" etc.
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
end
end
If you have only one of the sorting types enabled, there will only be one layer of folders, and you’ll have to do something like this:
for wordNumber, word in frame:GetChildren() do
print("Word "..wordNumber) -- "Word 1", "Word 2" etc.
-- 'word' will be a folder.
for characterNumber, character in word:GetChildren() do
print("Character "..characterNumber) -- "Character 1", "Character 2" etc.
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
end
Alternatively, you can use the GetCharacters
function, which will return all of the characters.
This function is optimized, and respects all sorting types.
You can simply loop through the table like this:
local characters = textPlus.GetCharacters(frame)
for characterNumber, character in characters do
print("Character "..characterNumber) -- "Character 1", "Character 2" etc.
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
Specific indexing and looping
You can always access the exact line, word or character number you want by indexing like this:
frame["1"]
With some sorting enabled, you’ll be able to loop through specific lines and words.
Character (requires you to have no sorting)
for _, character in frame:GetChildren() do
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
Word (requires word sorting)
local word = frame["1"] -- Word sorting.
local word = frame["1"]["1"] -- Line and word sorting.
for _, character in word:GetChildren() do
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
Line (requires line sorting)
local line = frame["1"]
-- Line and word sorting:
for _, word in line:GetChildren() do
-- 'word' will be a folder.
for _, character in word:GetChildren() do
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
end
-- Line sorting:
for _, character in line:GetChildren() do
-- For Roblox fonts, 'character' will be a TextLabel.
-- For custom fonts, 'character' will be an ImageLabel.
end
Transform and style
All characters are instances, that can be directly modified.
As I’ve noted a few times already:
- Roblox fonts: TextLabels
- Custom fonts: ImageLabels
And don’t forget to be creative!
🛠️ Custom fonts
Font generation tool
We’re going to be using SnowB to generate the necessary font files.
It’s a free, simple bitmap font generation website.
Character selection
You’ll have to specify which characters you want to include in your custom font.
This is done at the Glyphs
section in the top-left corner.
By default, there should be all the characters you’ll need.
But you might want to get rid of the №
character.
Why is it there? I don’t know.
If you’re going to be using any more characters, feel free to add them.
Font settings
Head over to the Font
section, located right below Glyphs
.
Get a .ttf
or .otf
file (a font file), whether it’s one of your own or one you found online.
Press ADD FONT FILE
, and select your font file.
Choose the smallest possible Font Size
that covers your largest intended use case. Avoid extreme values (like 1,000px) unless absolutely necessary, since the images have to be replicated from server to client.
Fill settings
Head over to the Fill
section, located in the top-right corner.
Set Color
to white. Make sure it’s fully white (255, 255, 255, 100).
Export the files
Click Export
in the top bar.
Input a File Name
for your font.
For the Export Type
, select BMFont XML
.
Press Save
in the bottom-right corner of the pop-up.
It should save a .xml
and a .png
file.
Convert XML to Lua format
I’ve made this step nice and simple with a program that does this for you.
Download my converter on GitHub.
Unzip/extract the zip file.
You should get a folder with a Convert.exe
file inside.
Drag your .fnt
file into the folder where the Convert.exe
file is.
Then simply open the Convert.exe
file.
It might warn you, saying it might be a threat (virus). This is simply because I haven’t registered the file, as it’s extremely expensive to do so. The code is open-source.
After a few short seconds, you should see a new .lua
file.
Upload the image and get its id
Upload the image at the creator hub.
Then go to your images.
Find your image, click the three dots on it, and then click Copy Asset ID
.
Import font data to Text+
Find the TextPlus
module in your explorer.
Open the CustomFonts
module located inside of it.
Add your font like this:
return {
MyFont = -- Paste Lua XML file content here.
}
Add your image id for the font in the same table as the Size
and Characters
, like this:
MyFont = {
Image = 0, -- Image id.
-- From Lua XML file:
Size = 32,
Characters = {
}
}
For fonts that have multiple weights and/or styles, it’s recommended to use the following format:
return {
-- Fonts.
MyFont = {
-- Weights.
Bold = {
-- Styles.
Italic = {
Image = 0, -- Image id.
-- From Lua XML file:
Size = 32,
Characters = {
}
}
}
}
}
Use the custom font
Using custom fonts is extremely simple.
Instead of providing a Font
object, directly reference the custom font table like this:
textPlus.Create(
frame,
"Text",
{
Font = textPlus.CustomFonts.MyFont -- Don't require the fonts module!
}
)
Don’t forget to stay up-to-date!
It’s highly recommended to have the latest version at all times. This ensures:
- Newest features.
- Best performance.
- Little to no bugs.
You can view all releases (versions) and what they contain at the GitHub repository.
Major updates will be posted here, in the replies section, too.
Use this post as documentation for the module.
All documentation will stay up-to-date in this post.
Share your thoughts and creations!
I’d love to see what you guys are able to do with this, so consider sharing your works!
But most importantly:
- Report any bugs or mistakes you find for this asset and post!
- Consider providing feedback to help me and the asset improve!
Like what you're seeing?
Check out more from me!
∙ Signal+|Insanely optimized script signal
Tags
module text rendering custom fonts advanced control dialogue animation creativity features open source scripting ui gui graphical interface design quality performance optimization customization