Heyo,
I’d like to share a module that I’ve used for my own games. With this module it’s possible to create pieces of text which can be customized down to the individual characters. Each character’s properties are individually modifiable.
GIFs
Random effects on SurfaceGui
Text Drawing on ScreenGui
Random effects on BillboardGui
Sorry for the lag in some of the videos, my computer is a bit of a potato especially when recording.
How do I use it? + Examples
It’s quite simple to use, you require the module and create a new instance using Module.new(TextLabel). The TextLabel would be your placeholder TextLabel you put in your Gui object of choice. Once you’ve done that you can use the new instance’s :GetCharacters() function to modify each character in your text sequence. Here’s an few examples.
Simple Randomization
-- Modules
local StringLabel = require(game.ReplicatedStorage:WaitForChild("StringLabel"))
-- Variables
local stringLabel = StringLabel.new(script.Parent:WaitForChild("TestLabel"))
local characters = stringLabel:GetCharacters()
local numCharacters = #characters
local fontTable = { Enum.Font.Gotham, Enum.Font.GothamSemibold, Enum.Font.GothamBold, Enum.Font.GothamBlack }
-- Script Body
while true do
local color1 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
local color2 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
for index, character in pairs(characters) do
stringLabel:SetCharacterTextColor(index, color1:Lerp(color2, index / numCharacters))
stringLabel:SetCharacterTextTransparency(index, math.random(100) / 100)
wait()
end
wait()
end
Effects from the GIFs
-- Services
local runService = game:GetService("RunService")
-- Modules
local StringLabel = require(game.ReplicatedStorage:WaitForChild("StringLabel"))
-- Variables
local stringLabel = StringLabel.new(script.Parent:WaitForChild("TestLabel"))
local characters = stringLabel:GetCharacters()
local numCharacters = #characters
local fontTable = { Enum.Font.Gotham, Enum.Font.GothamSemibold, Enum.Font.GothamBold, Enum.Font.GothamBlack }
local baseColor = Color3.fromRGB(255, 255, 255)
---- Functions
-- Util
function shuffle(tab)
local size = #tab
for i = size, 1, -1 do
local random = math.random(size)
tab[i], tab[random] = tab[random], tab[i]
end
return tab
end
local function reset()
stringLabel:SetTextTransparency(0)
stringLabel:SetTextColor(baseColor)
stringLabel:SetRotation(0)
end
-- Effects
local function rainbowWave()
local textLength = string.len(stringLabel:GetText())
local offset = 0
local counter = 0
local mult = 2
local baseSize = 1 / (textLength * mult)
while counter < 150 do
for index, character in pairs(characters) do
stringLabel:SetCharacterTextColor(index, Color3.fromHSV(baseSize * ((index + offset) % (textLength * mult)), 1, 1))
end
offset = offset + 1
counter = counter + 1
runService.RenderStepped:Wait()
end
end
local function randomGradient()
local color1 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
local color2 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
for index, character in pairs(characters) do
stringLabel:SetCharacterTextColor(index, color1:Lerp(color2, index / numCharacters))
runService.RenderStepped:Wait()
end
end
local function randomColorAndTransparency()
for index, character in pairs(characters) do
stringLabel:SetCharacterTextColor(index, Color3.fromRGB(math.random(255), math.random(255), math.random(255)))
stringLabel:SetCharacterTextTransparency(index, math.random(100) / 100)
runService.RenderStepped:Wait()
end
end
local function randomCharacterHighlight()
local randomCharacterIndices = {}
for index = 1, numCharacters do
table.insert(randomCharacterIndices, index)
end
shuffle(randomCharacterIndices)
for _, index in pairs(randomCharacterIndices) do
stringLabel:SetCharacterTextColor(index, Color3.fromRGB(0, 0, 0))
runService.RenderStepped:Wait()
end
for _, index in pairs(randomCharacterIndices) do
stringLabel:SetCharacterTextColor(index, Color3.fromRGB(255, 255, 255))
runService.RenderStepped:Wait()
end
end
local function randomWaveGradient()
local color1 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
local color2 = Color3.fromRGB(math.random(255), math.random(255), math.random(255))
local fadeSize = 25
for i = 1, 50 do
stringLabel:SetTextColor(baseColor:Lerp(color1, i / 50))
runService.RenderStepped:Wait()
end
stringLabel:SetTextColor(color1)
for index = 1, numCharacters + fadeSize do
for i = 1, fadeSize do
if index - i >= 1 then
stringLabel:SetCharacterTextColor(index - i, color2:Lerp(color1, i / fadeSize))
end
end
if index <= numCharacters then
stringLabel:SetCharacterTextColor(index, color2)
end
for i = 1, fadeSize do
if index + i <= numCharacters then
stringLabel:SetCharacterTextColor(index + i, color2:Lerp(color1, i / fadeSize))
end
end
runService.RenderStepped:Wait()
end
end
local function randomRotation()
for index, character in pairs(characters) do
stringLabel:SetCharacterRotation(index, math.random(-225, 225) / 10)
runService.RenderStepped:Wait()
end
end
-- Script Body
local effects = { rainbowWave, randomGradient, randomColorAndTransparency, randomCharacterHighlight, randomWaveGradient, randomRotation }
local counter = 1
while true do
for _, callback in pairs(effects) do
reset()
callback()
wait(1)
end
end
Text Drawing
-- Services
local replicatedStorage = game:GetService("ReplicatedStorage")
local userInputService = game:GetService("UserInputService")
local runService = game:GetService("RunService")
-- Modules
local StringLabel = require(replicatedStorage:WaitForChild("StringLabel"))
-- Variables
local text = script.Parent:WaitForChild("Text")
local drawStringLabel = nil
local mouseDown = false
local lastPosition = nil
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
-- Functions
local function onMouseDown()
while mouseDown do
local position = Vector2.new(mouse.X, mouse.Y)
if position ~= lastPosition then
lastPosition = position
local absolutePositions, absoluteSizes = drawStringLabel:GetCharacterAbsolutePositionsAndSizes()
for index, character in pairs(drawStringLabel:GetCharacters()) do
local absolutePosition = absolutePositions[index]
local absoluteSize = absoluteSizes[index]
if position.X > absolutePosition.X and position.X < absolutePosition.X + absoluteSize.X then
if position.Y > absolutePosition.Y and position.Y < absolutePosition.Y + absoluteSize.Y then
drawStringLabel:SetCharacterTextColor(index, Color3.fromRGB(255, 255, 255))
end
end
end
end
runService.RenderStepped:Wait()
end
end
local function setup()
drawStringLabel = StringLabel.new(text)
spawn(function()
local checkTime = tick()
while true do
if tick() - checkTime >= 15 then
drawStringLabel:SetTextColor(Color3.fromRGB(0, 0, 0))
checkTime = tick()
end
wait(1)
end
end)
userInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if not gameProcessedEvent then
if input.UserInputType == Enum.UserInputType.MouseButton1 then
mouseDown = true
onMouseDown()
end
end
end)
userInputService.InputEnded:Connect(function(input, gameProcessedEvent)
if not gameProcessedEvent then
if input.UserInputType == Enum.UserInputType.MouseButton1 then
mouseDown = false
end
end
end)
end
-- Body
setup()
I made it open source so anyone can use it, modify it, etc. to their liking or needs. I enabled copying on the Roblox page.
Thanks for reading, I hope I didn’t mess up the spelling and grammar too much (English isn’t my native language) and I hope it’ll be useful to some people. If there’s any issues or if you have any questions (related to my module, not Roblox or LUA.) then let me know in the replies.
Disclaimer:
There may be a few bugs that I haven’t caught yet, like I said this was primarily for private use and I tested it the best I could, but may have missed something. In which case leave a reply and I’ll try to fix them.
Edit:
I forgot to mention that this module only works locally. (Client-side)