In-Experience Text Chat

With the in-experience text chat system on Roblox, players can communicate with each other using text-based messages in live sessions. The system provides a set of methods and events for extending and customizing chat functionalities, such as delivering messages based on customized requirements, adding special permissions or moderation to specific players, and creating custom commands to execute specific actions.

This guide covers the chat workflow and approaches for extending the functionalities of the chat system. For more information on customizing the chat user interface (UI), see Customizing Text Chat.

Chat Workflow

The in-experience text chat system consists of both mutable classes that you can extend for customized chat delivery behaviors and immutable data objects representing certain chat elements returned by mutable classes.

Mutable Chat Classes

The in-experience text chat system provides the following mutable classes:

  • TextChatService — This singleton class is responsible for managing the overall chat system, including handling chat message filtering, moderation, and user permissions. Accessible from the server, it provides a set of methods and events that other text chat APIs or player actions can invoke through the chat delivery workflow.
  • TextChannel — This class represents a text chat channel that passes player-sent chat messages from the client to the server and displays them to other players based on permissions. You can use it to create, modify, and manage text channels in your experience. Additionally, you can create multiple text channels to group players together for chat purposes, such as allowing players to chat with their group members that are not visible to others.
  • TextChatCommand — This class enables you to create custom chat commands that allow players to invoke specific actions or behaviors by typing special characters followed by a command name. Chat commands are helpful for adding additional functionality and interactivity to the chat experience. You can also use them to create admin commands to manage and moderate your experience with shortcuts.

Immutable Chat Objects

The in-experience text chat system includes the following immutable objects with read-only properties that you can't modify:

  • TextChatMessage: This object represents a single chat message in a text chat channel with basic information such as the sender of the message, the original message, the filtered message, and the creation timestamp.
  • TextSource: This object represents a message sender in a text chat channel with detailed permissions of a player in the channel. If a player is in multiple text chat channels, they can have multiple text sources as well.

Chat Flowchart

Through the chat message sending and delivery process, methods, callbacks, and events of mutable chat classes work alongside immutable chat objects on three sides of the client‑server model:

  • The sending client, which is the local device of a player sending a message.
  • Receiving clients, which are other players' local devices.
  • The server, which is the central processor for receiving the message from the sending client and handles the delivery to receiving clients.
A flowchart of the in-experience text chat workflow

As the flowchart shows, the in-experience text chat system processes a chat message through the following steps:

  1. A player sends a message from their local device, triggering the TextChannel:SendAsync() method. This method processes the message and determines whether it's a chat command or a regular chat message.
  2. If the player input is a chat command, it fires the TextChatCommand.Triggered event to perform the action you have defined for the command.
  3. If the player input is a regular chat message, it fires TextChatService.SendingMessage to display the original message to the sender on the sending client. At the same time, the TextChannel:SendAsync() passes the message to the server.
  4. The server fires TextChannel.ShouldDeliverCallback to determine whether to deliver the message to other players based on the permissions you set and Roblox community filtering requirements.
  5. If TextChannel.ShouldDeliverCallback determines that message is eligible to deliver to other players, the server applies any filters and fires TextChannel.OnIncomingMessage twice:
    1. The first time on the sending client to signal that the server is processing the message through the TextChatService.MessageReceived event. This also replaces the local message on the sending client with the incoming message to the display on receiving clients. The message can be identical if the original message doesn't require filtering.
    2. The second time is on the receiving client to trigger the TextChatService.MessageReceived event to display the message to other players.

There are several areas of the chat system workflow that you can extend and customize the behavior, but the steps of how the system operates remain the same.

Customizing Message Delivery Behaviors

In addition to sticking with the default chat message delivery behavior, you can use TextChannel.ShouldDeliverCallback to add permissions and specific behaviors to determine whether players can receive a message for customized engagement, such as:

  • Supporting group-based chat that only players in the same group or squad can communicate between.
  • Supporting proximity-based chat where players can only send messages to those close to them.
  • Preventing players with certain attributes from sending messages to others. For example, disallow players with a death status to send messages to alive players.
  • Adding the guessing competition feature where correct answers in chat are not visible to other players.

The following example shows how to implement exclusive chat for player characters who are close to each other in locations. It extends the callback with a function using TextSource to identify the locations of a player who might be a potential message receiver. If this function returns false, it means that the player character locates further than the preset valid range from the message sender's character, so the system doesn't deliver the message to that player.


local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
-- This example uses the general channel; you can replace this with a dedicated channel
local generalChannel: TextChannel = TextChatService:WaitForChild("TextChannels").RBXGeneral
-- Define a function to get the position of a player's character
local function getPositionFromUserId(userId: number)
-- Get the player associated with the given user ID
local targetPlayer = Players:GetPlayerByUserId(userId)
-- If the player exists, get their character's position.
if targetPlayer then
local targetCharacter = targetPlayer.Character
if targetCharacter then
return targetCharacter:GetPivot().Position
end
end
-- Return a default position if the player or character cannot be found
return Vector3.zero
end
-- Set the callback for the general channel to control message delivery
generalChannel.ShouldDeliverCallback = function(textChatMessage: TextChatMessage, targetTextSource: TextSource)
-- Get the positions of the message sender and target
local sourcePos = getPositionFromUserId(textChatMessage.TextSource.UserId)
local targetPos = getPositionFromUserId(targetTextSource.UserId)
-- If the distance between the sender and target is less than 50 units, deliver the message
return (targetPos - sourcePos).Magnitude < 50
end

Creating Custom Commands

The in-experience text chat system has built-in chat commands for common purposes, such as creating team-based chat channels and playing avatar emote. You can enable them by setting TextChatService.CreateDefaultCommands and TextChatService.CreateDefaultTextChannels to true through scripting or in Studio settings. You can also add custom commands using TextChatCommand. Players sending a defined command in the chat input bar trigger a callback defined by TextChatCommand.Triggered to perform your customized actions.

The following example shows how to create a chat command that allows players to increase or decrease their character's size when they input /super or /mini.

  1. Insert a TextChatCommand instance inside TextChatService.

  2. Rename it to SizeCommand.

  3. Set its PrimaryAlias property to /super and its SecondaryAlias to /mini.

  4. Insert the following Script inside ServerScriptService to define a callback for the chat command that scales the character's size.

    Script

    local TextChatService = game:GetService("TextChatService")
    local Players = game:GetService("Players")
    local sizeCommand: TextChatCommand = TextChatService:WaitForChild("SizeCommand")
    sizeCommand.Triggered:Connect(function(textSource, message)
    local scaleMult = 1
    local messageWords = string.split(message, " ")
    if messageWords[1] == "/super" then
    scaleMult = 2
    elseif messageWords[1] == "/mini" then
    scaleMult = 0.5
    end
    local player = Players:GetPlayerByUserId(textSource.UserId)
    if player then
    local character = player.Character
    if character then
    local humanoid = character:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    for _, child in humanoid:GetChildren() do
    if child:IsA("NumberValue") then
    child.Value *= scaleMult
    end
    end
    end
    end
    end
    end)

Migrating From Legacy Chat

This section assists you in migrating from the legacy chat system by providing alternative methods for implementing common chat functionalities and behaviors using the in-experience text chat system.

To switch the chat system of an existing experience from the legacy chat system to the in-experience text chat system:

  1. In the Explorer window, select TextChatService.

  2. In the Properties window, find the ChatVersion dropdown and select TextChatService.

Basic Functionalities

Though both systems share the same basic chat functionalities, the in-experience text chat system implementations are in general more sustainable and easier to iterate on.

FunctionalityLegacy ChatIn-Experience Text ChatDifferences
Send a Chat MessagePlayers:Chat()TextChannel:SendAsync()The TextChatService:SendAsync() method supports more advanced chat features such as rich text formatting and message priority. It also includes built-in filtering to help prevent inappropriate messages from being sent.
Implement Messaging CallbacksChat:InvokeChatCallback()
Chat:RegisterChatCallback()
TextChatService.SendingMessage
TextChatService.OnIncomingMessage
The legacy chat system binds a function to chat system events for delivering messages. The two methods of the in-experience text chat system have more flexibilities and customization options.
Add Custom Chat CommandsChatService/ChatCommand moduleTextChatCommandThe in-experience text chat system has a dedicated class representing a text command for customization rather than using a legacy chat module.
Display a System MessageStarterGui:SetCore() using "ChatMakeSystemMessage"TextChannel:DisplaySystemMessage()The TextChannel.OnIncomingMessage callback can return a TextChatMessageProperties instance to customize the message appearance.
Disable ChatGame Settings in Studio and ChatWindow/ChatSettings module for hiding the chat windowChatWindowConfiguration.Enabled

Message Filtering

The in-experience text chat system automatically filters chat messages based on each player's account information, so you don't need to manually implement text filtering for all kinds of chat messages.

FunctionalityLegacy ChatIn-Experience Text Chat
Filter Message for Individual PlayerChat:FilterStringAsync()n/a
Filter Broadcasting MessagesChat:FilterStringForBroadcast()n/a

Window and Bubble Chat

Both the chat window and bubble chat behavior and customization options of the in-experience text chat system are identical to those of the legacy chat system. As the legacy chat system only allows customization using chat modules or the Players container, the in-experience text chat system provides dedicated classes, ChatWindowConfiguration and BubbleChatConfiguration, to manage all chat window and bubble chat properties respectively. Additionally, you can easily adjust and preview your bubble chat appearance and behavior properties using Studio settings instead of having to script them all.