Roblox 通过 TextChatService 提供玩家在实时会话中进行基于文本的信息传递,TextChatService 是一个单例类,负责管理整体聊天系统,包括聊天消息过滤、监管和用户权限。该服务具有其标准功能,并提供了一组方法和事件以扩展和自定义聊天,例如根据 自定义要求 传递消息,为特定玩家添加特殊权限或监管,以及创建 自定义命令 执行特定操作。
UI 配置
TextChatService 提供了一个默认 UI,可以根据您的游戏需求进行自定义。禁用其中任何配置可以隐藏其相关的 UI 元素。如果需要,您还可以用自定义界面替换这些 UI 元素:
渠道、消息和命令
TextChannel — 文本频道将用户发送的消息从客户端传递到服务器,后者根据权限将其显示给其他用户。文本频道必须是 TextChatService 的子元素才能正常工作。
TextSource — 在 TextChannel 中的用户。当调用 AddUserAsync() 时,文本源会直接添加为 TextChannel 的子元素。文本源包含用户在频道的详细权限,例如他们发送消息的能力。如果一个用户在多个文本频道中,他们将关联多个文本源。
TextChatMessage — 文本频道中的一条消息。聊天消息包含基本信息,例如消息的发送者、原始消息、过滤后的消息以及创建时间戳。
TextChatCommand — 允许用户通过发送与 PrimaryAlias 或 SecondaryAlias 属性匹配的消息来调用特定操作或行为。聊天命令必须是 TextChatService 的子元素才能正常工作。
聊天流程图
文本聊天使用 客户端-服务器 模型,包括 发送客户端、服务器 和 接收客户端。

玩家从其本地设备发送消息,触发 TextChannel:SendAsync() 方法。该方法处理消息并确定其是聊天命令还是常规聊天消息。
如果消息是聊天命令,它会触发 TextChatCommand.Triggered 事件以执行指定的操作。无需进行进一步步骤。
如果消息是常规聊天消息,则会触发 TextChatService.SendingMessage 事件,以在发送客户端上显示该消息。与此同时,TextChannel:SendAsync() 将消息传递给服务器。
服务器触发 TextChannel.ShouldDeliverCallback 来确定是否根据权限和 Roblox 社区过滤要求将消息传递给其他玩家。
如果 TextChannel.ShouldDeliverCallback 确定消息可以传递给其他玩家,则服务器应用任何过滤器,并两次触发 TextChannel.OnIncomingMessage:
第一次是在发送客户端上,并通过 TextChatService.MessageReceived 事件表示服务器正在处理该消息。此事件用服务器处理的消息替换发送客户端上的本地消息。如果原始消息不需要过滤,则消息是相同的。
第二次是在接收客户端上,触发 TextChatService.MessageReceived 事件,将消息显示给其他玩家。
文本聊天钩子和回调
TextChatService API 鼓励在聊天消息的外观和传递之间保持清晰的分离。多个文本聊天系统的实例提供钩子和回调,以在集中且清晰的位置进行格式化。

条件传递消息
TextChannel.ShouldDeliverCallback 回调应仅在服务器端定义。每当发送消息时,此回调会为文本频道的每个 TextSource 子元素触发,以确定是否应传递该消息。该回调可用于实现可能依赖于额外游戏上下文的自定义消息传递逻辑,例如:
- 基于接近度的聊天,用户只能向与自己接近的人发送消息。
- 防止具有某些属性的用户向其他用户发送消息。
自定义消息显示
默认 TextChatService UI 依赖 富文本 来格式化和自定义消息的显示方式。您可以使用以下回调格式化在展示给用户之前的消息,例如为用户名添加颜色或 聊天标签 或格式化消息内容。
以下回调会在即将展示的每个 TextChatMessage 上被调用,这让您可以根据 TextChannel、TextSource,或 TextChatMessage 内容自定义聊天窗口外观。当客户端发送消息时,在消息发送到服务器时,这些回调会被调用一次,此时 TextChatMessage.Status 值将为 Enum.TextChatMessageStatus.Sending。一旦消息被服务器接收并传递给其他用户,发送客户端将再次收到消息,并更新 Enum.TextChatMessageStatus 值。
- TextChatService.OnIncomingMessage — 此回调应仅在客户端定义。当收到消息时(无论是来自服务器还是本地客户端刚刚发送的消息),会触发此回调。该回调会在从所有 TextChannel 实例接收到的每个 TextChatMessage 上被调用,并且是向用户展示消息之前的第一个处理者。
- TextChannel.OnIncomingMessage — 此回调应仅在客户端定义。当从服务器接收到消息时,会触发此回调。该回调会在从 TextChannel 接收到的每个 TextChatMessage 上被调用。从 TextChatService.CreateDefaultTextChannels 创建的默认 TextChannel 实例具有此回调定义,并可被重写。
- TextChatService.OnBubbleAdded — 此回调应仅在客户端定义。使用它来自定义聊天气泡的外观,与聊天窗口 UI 中消息的外观无关。
- TextChatService.OnChatWindowAdded — 此回调应仅在客户端定义。使用它来自定义聊天窗口 UI 中聊天消息的外观,与气泡中的消息外观无关。
从旧聊天系统迁移
本节通过提供实现常见聊天功能和行为的替代方法,帮助您从旧聊天系统迁移到 TextChatService。
在 资源管理器 窗口中,选择 TextChatService。
在 属性 窗口中,找到 ChatVersion 下拉菜单并选择 TextChatService。

基础功能
尽管两个系统共享相同的基本聊天功能,但 TextChatService 的实现通常更可持续,更易于迭代。
| 功能 | 旧聊天 | TextChatService | 差异 |
|---|---|---|---|
| 发送聊天消息 | Players:Chat() | TextChannel:SendAsync() | SendAsync() 方法支持更高级的聊天功能,如富文本格式和消息优先级。它还包括内置过滤器以帮助防止不当消息的发送。 |
| 实现消息回调 | Chat:InvokeChatCallback() Chat:RegisterChatCallback() | TextChatService.SendingMessage TextChatService.OnIncomingMessage | 旧聊天系统将函数绑定到聊天系统事件以传递消息。TextChatService 的这两个方法提供了更好的灵活性和自定义功能。 |
| 添加自定义聊天命令 | ChatService/ChatCommand 模块 | TextChatCommand | TextChatService 具有专门针对文本命令的类,而不是使用旧的聊天模块。 |
| 显示系统消息 | StarterGui:SetCore() 使用 ChatMakeSystemMessage | TextChannel:DisplaySystemMessage() | TextChannel.OnIncomingMessage 回调可以返回 TextChatMessageProperties 实例以自定义消息外观。 |
| 禁用聊天 | 体验设置 在 Studio 和 ChatWindow/ChatSettings 模块中隐藏聊天窗口 | ChatWindowConfiguration.Enabled |
消息过滤
TextChatService 根据每个玩家的账户信息自动过滤聊天消息,因此您无需手动实现所有类型聊天消息的文本过滤。
| 功能 | 旧聊天 | TextChatService |
|---|---|---|
| 为单独玩家过滤聊天消息 | Chat:FilterStringAsync() | 自动 |
| 过滤广播消息 | Chat:FilterStringForBroadcast() | 自动 |
窗口和气泡聊天
TextChatService 的 聊天窗口 和 气泡聊天 行为和自定义选项与旧聊天系统相同。由于旧聊天系统仅允许通过聊天模块或 Players 容器进行自定义,因此该服务提供专门的类(ChatWindowConfiguration 和 BubbleChatConfiguration)来管理所有聊天窗口和气泡聊天属性。此外,您可以使用 Studio 设置轻松调整和预览气泡聊天的外观和行为属性,而无需编写脚本。
迁移发言人“额外数据”
旧的 Lua 聊天系统允许开发者在 Speaker 类上使用 SetExtraData。这些数据用于格式化名称颜色、聊天颜色或为特定发言人应用名称标签。
旧聊天系统 SetExtraData
-- 在旧聊天系统中设置发言人额外数据的示例
ChatService.SpeakerAdded:Connect(function(playerName)
local speaker = ChatService:GetSpeaker(playerName)
speaker:SetExtraData("NameColor", Color3.fromRGB(255, 255, 55))
speaker:SetExtraData("ChatColor", Color3.fromRGB(212, 175, 55))
speaker:SetExtraData("Tags", {{TagText = "YourTagName", TagColor = Color3.fromRGB(0, 255, 0)}, {TagText = "OtherTagName", TagColor = Color3.fromRGB(255, 0, 0)}})
end)
TextChatService 没有与 SetExtraData 的直接等效项。相反,使用 回调 如 OnWindowAdded 来使用富文本自定义基于消息的 TextSource 的消息外观。
以下是通过访问 Player 对象上的属性模拟旧 Lua 聊天的“额外数据”的示例:
TextChatService SetAttributes
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
player:SetAttribute("NameColor", Color3.fromRGB(255, 255, 55))
player:SetAttribute("ChatColor", Color3.fromRGB(212, 175, 55))
player:SetAttribute("isYourTag", true)
player:SetAttribute("isOtherTag", true)
end)
然后,您可以使用 OnChatWindowAdded 回调来根据玩家上设置的属性自定义聊天窗口的外观:
TextChatService OnChatWindowAdded
local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
TextChatService.OnChatWindowAdded = function(textChatMessage)
local textSource = textChatMessage.TextSource
if textSource then
local player = Players:GetPlayerByUserId(textSource.UserId)
if player then
local overrideProperties = TextChatService.ChatWindowConfiguration:DeriveNewMessageProperties()
overrideProperties.PrefixText = textChatMessage.PrefixText
overrideProperties.Text = textChatMessage.Text
local nameColor = player:GetAttribute("NameColor")
if nameColor and typeof(nameColor) == "Color3" then
overrideProperties.PrefixTextProperties.TextColor3 = nameColor
end
local chatColor = player:GetAttribute("ChatColor")
if chatColor and typeof(chatColor) == "Color3" then
overrideProperties.TextColor3 = chatColor
end
local isYourTag = player:GetAttribute("isYourTag")
if isYourTag == true then
overrideProperties.PrefixText = `<font color='rgb(0, 255, 0)'>[YourTag]</font> {overrideProperties.PrefixText}`
end
local isOtherTag = player:GetAttribute("isOtherTag")
if isOtherTag == true then
overrideProperties.PrefixText = `<font color='rgb(255, 0, 0)'>[OtherTag]</font> {overrideProperties.PrefixText}`
end
return overrideProperties
end
end
return nil
end