I quickly rewrote it to help out those who aren’t sure about how to implement multi-line support for their custom chat systems. The code I ended up with about 1.5 years ago contains a lot more “bad practices” and isn’t nearly as clean to read.
Essentially what I’m the script is doing is that it’s iterating through the message text and filling up a variable called PixelsSpent
until it exceeds the variable PixelBudgetPerLine
- which is basically how many pixels wide the text can be before it doesn’t fit in the message frame. So this is basically just text wrapping.
This code doesn’t try to keep whole words in the same line but can simply cut a word mid-through and continue on the next line - you’ll need to implement this yourself if wanted. It also automatically adjusts the ScrollingFrame’s CanvasSize and scrolls with it.
There also is no line nor text length limit - meaning your text can be as long as you want and infinitely make new lines.
I’m doing most of this in Offset and not Scale so if Scale is something you’d want, then you’ll have to add this yourself.
Video:
Code:
--|| Variables
local ScrollingFrame = script.Parent.ScrollingFrame
local TextService = game:GetService("TextService")
-- Config
local PixelsPerLine = 20
local PredefinedTextSize = 16
local PredefinedFont = Enum.Font.SourceSans
--|| Functions
function GetSize(String)
return TextService:GetTextSize(String, PredefinedTextSize, PredefinedFont, Vector2.new(math.huge, math.huge)).X
end
function NewLabel(String, Position, Color)
local Label = Instance.new("TextLabel")
Label.BackgroundTransparency = 1
Label.TextSize = PredefinedTextSize
Label.Font = PredefinedFont
Label.Text = String
Label.Position = Position
Label.Size = UDim2.new(0, GetSize(String), 0, PixelsPerLine)
Label.TextColor3 = Color or Color3.fromRGB(0, 0, 0)
return Label
end
function NewMessage(Sender, MessageText)
Sender = Sender .. ": "
local Message = script.Template:Clone()
Message.Parent = ScrollingFrame
local PixelBudgetPerLine = Message.Container.AbsoluteSize.X
local PixelsSpent = 0
local Line = 0
-- Sender
local Label = NewLabel(Sender, UDim2.new(0, PixelsSpent, 0, 20*Line), Color3.fromRGB(92, 95, 255))
Label.Parent = Message.Container
PixelsSpent += GetSize(Sender)
-- Message w/iterations
local SubStart = 1
for i = 1, #MessageText do
local String = string.sub(MessageText, SubStart, i)
local StringSize = GetSize(String)
if PixelsSpent + StringSize > PixelBudgetPerLine then
local String = string.sub(MessageText, SubStart, i-1)
local StringSize = GetSize(String)
local Label = NewLabel(String, UDim2.new(0, PixelsSpent, 0, 20*Line), Color3.fromRGB(43, 43, 43))
Label.Parent = Message.Container
PixelsSpent = 0
Line += 1
SubStart = i
continue
end
if i == #MessageText then
local Label = NewLabel(String, UDim2.new(0, PixelsSpent, 0, 20*Line), Color3.fromRGB(43, 43, 43))
Label.Parent = Message.Container
end
end
Message.Size = UDim2.new(Message.Size.X.Scale, Message.Size.X.Offset, 0, (Line+1) * PixelsPerLine)
-- Scrolling frame
ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, ScrollingFrame.UIListLayout.AbsoluteContentSize.Y)
ScrollingFrame.CanvasPosition = Vector2.new(0, ScrollingFrame.CanvasSize.Y.Offset)
end
while wait(1) do
NewMessage("Avallachi" .. math.random(1, 5000), "This is quite the long and unnecessary test message, but it's needed because I'm not very creative ;)")
end
Place file (.rblx)
chat.rbxl (25.0 KB)
I hope this was helpful to those of you who are still trying to figure this out.