Roblox 通过 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 上调用。默认的 TextChannel 实例是从 TextChatService.CreateDefaultTextChannels 创建的,具有此回调定义,并且可以被覆盖。
- 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 实例以自定义消息外观。 |
| 禁用聊天 | ChatWindow/ChatSettings 模块用于隐藏聊天窗口 | ChatWindowConfiguration.Enabled |
消息过滤
TextChatService 会根据每个玩家的帐户信息自动过滤聊天消息,因此您无需手动实现所有类型聊天消息的文本过滤。
| 功能 | 遗留聊天 | TextChatService |
|---|---|---|
| 为单个玩家过滤聊天消息 | Chat:FilterStringAsync() | 自动 |
| 过滤广播消息 | Chat:FilterStringForBroadcast() | 自动 |
窗口和气泡聊天
TextChatService 的 聊天窗口 和 气泡聊天 行为和自定义选项与遗留聊天系统相同。由于遗留聊天系统仅允许使用聊天模块或 Players 容器进行自定义,因此该服务提供专门的类(ChatWindowConfiguration 和 BubbleChatConfiguration)来管理所有聊天窗口和气泡聊天属性。此外,您可以轻松调整和预览气泡聊天的外观和行为属性,使用 Studio 设置,而不必全部编写脚本。
迁移发言者“额外数据”
遗留 Lua 聊天系统允许开发者在 Speaker 类上使用 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 聊天的“额外数据”的示例:
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 回调根据设置在玩家上的属性自定义聊天窗口的外观:
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