聊天和字幕模式
向场景中添加可滚动的聊天历史、实时字幕或两者,并配置每种转录显示的外观和行为。
ConvaiManager.ActiveManager.Transcripts (ConvaiTranscripts) 提供对一段对话的两个独立视图:与实时语音对齐的字幕,以及持久的轮次历史。本页介绍如何添加 SubtitleTranscriptUI 用于字幕, ChatTranscriptUI 用于历史,或两者都添加——两者都从同一个门面读取并独立更新,因此添加其中一个不会移除或替换另一个。
选择你需要的投影
字幕
CurrentCaptions, CaptionsChanged, SubscribeCaptions(...)
SubtitleTranscriptUI (参考脚本)
低延迟、与语音对齐的文本。短暂存在——不会作为聊天历史保存
时间线
CurrentTimeline, Changed, Subscribe(...), SubscribeCommitted(...)
ChatTranscriptUI (已发布组件)
可持久保存、可滚动的对话历史,便于审阅、回放或导出
不存在一个单一的模式开关可以启用一种投影而牺牲另一种。自定义组件可以从 ConvaiManager.ActiveManager.Transcripts 直接订阅任一投影,或两者都订阅:
using System;
using Convai.Domain.Models;
using Convai.Runtime.Components;
using UnityEngine;
public class TranscriptProjectionExample : MonoBehaviour
{
private IDisposable _captionSubscription;
private IDisposable _historySubscription;
private void OnEnable()
{
if (!ConvaiManager.ActiveManager.TryGetTranscripts(out ConvaiTranscripts transcripts)) return;
// 用于屏幕字幕的低延迟字幕
_captionSubscription = transcripts.SubscribeCaptions(OnCaption);
// 用于可滚动聊天日志的持久轮次历史
_historySubscription = transcripts.Subscribe(
OnHistoryChange,
new TranscriptSubscriptionOptions { ReplayExisting = true });
}
private void OnDisable()
{
_captionSubscription?.Dispose();
_historySubscription?.Dispose();
}
private void OnCaption(TranscriptCaption caption) { /* 更新字幕文本 */ }
private void OnHistoryChange(TranscriptChange change) { /* 更新聊天气泡 */ }
}两个已发布的显示组件也会遵守 ConvaiTranscripts.IsPresentationEnabled。当设置面板的 Transcript 开关关闭,或者 ConvaiRuntimeSettingsPatch 设置 TranscriptEnabled = false, ChatTranscriptUI 并且 SubtitleTranscriptUI 两者都会停止渲染——但 CurrentTimeline 仍会继续记录。关闭显示不会丢弃历史。
添加聊天历史显示
ChatTranscriptUI 将每一轮渲染为可滚动列表中的一个消息气泡,角色和玩家的轮次分列显示。轮次流式传输时气泡会实时更新,在轮次提交后则固定下来。
ChatTranscriptUI 检查器字段
scrollRect
ScrollRect 包含消息列表。自动滚动所必需
chatContainer
RectTransform 消息气泡 GameObject 的父对象
characterMessagePrefab
为每个角色轮次实例化的预制体
playerMessagePrefab
为每个玩家轮次实例化的预制体
chatInputField
可选 TMP_InputField 用于键入文本输入
fadeDuration
面板淡入/淡出动画所需秒数(默认 0.5)
canvasFader
CanvasFader 驱动淡入淡出动画
canvasGroup
CanvasGroup 控制淡入淡出期间的可交互性
ChatMessageBubble 检查器字段
每个消息气泡预制体都必须在其根节点包含一个 ChatMessageBubble 组件:
senderUI
TextMeshProUGUI 显示说话者姓名
messageUI
TextMeshProUGUI 显示转录文本
ChatTranscriptUI 使用该角色配置的 NameTagColor 为角色气泡的发送者姓名着色(来自 ConvaiCharacter 或其角色配置资源)。若要在脚本中覆盖此设置,请调用 bubble.SetSenderColor(Color).
调用 ChatTranscriptUI.ClearAll() 以销毁所有已渲染的消息气泡并重置面板。这只会清除可视显示——底层的轮次历史在 ConvaiManager.ActiveManager.Transcripts.CurrentTimeline 不受影响。有关注意事项,请参见 Transcript UI — 清除转录显示 。
添加字幕
SubtitleTranscriptUI 在固定位置显示一块单独的文本,由 SubscribeCaptions驱动。字幕定稿后,文本会在可配置的延迟后自动隐藏。
SubtitleTranscriptUI 仅以脚本形式提供——没有配套预制体。它是 SamplesShared中的参考实现;在修改前请将其复制到你自己的程序集,因为 SamplesShared 脚本会在 SDK 更新时被覆盖。
SubtitleTranscriptUI 检查器字段
subtitleText
—
TMP_Text 渲染字幕正文
speakerLabel
—
TMP_Text 渲染说话者姓名
subtitleContainer
—
GameObject 包裹两个文本元素,并切换开/关
fadeDuration
0.3
淡入/淡出动画所需秒数
canvasFader
—
CanvasFader 驱动淡入淡出动画
canvasGroup
—
CanvasGroup 控制可交互性
autoHideDelay
3.0
字幕定稿后等待隐藏的秒数
过滤器:
finalOnly
false
当 true时,只显示已定稿字幕;跳过流式文本
filterBySpeakerType
false
当 true,将字幕限制为 speakerType
speakerType
角色
TranscriptSpeakerType 在打开时按以下类型过滤( filterBySpeakerType Player,或, 角色系统 System)
speakerIdFilter
—
将字幕限制为特定说话者 ID
participantIdFilter
—
将字幕限制为特定房间参与者 ID(多人房间)
说话者标签颜色: 角色语音——青色;玩家语音——绿色。
为聊天消息添加反馈按钮
聊天气泡可以包含点赞/点踩反馈按钮,让用户对单个 AI 回复进行评分。
没有任何已发布组件会自动调用 ChatMessageBubble.SetInteractionID(string) 。在你的代码为某一轮调用它之前, ChatMessageBubble.SendFeedback(bool) 返回 false ,并且该消息的按钮不会高亮。
ChatMessageBubble 反馈 API
SetInteractionID(string interactionID)
在为此气泡发送反馈之前必需
SetAgentRegistry(IAgentRegistry agentRegistry)
角色查找所必需。由以下内容自动注入: ChatTranscriptUI
bool SendFeedback(bool isPositiveFeedback)
返回 true 如果 interactionID 已设置且在代理注册表中找到了该角色,则返回 false 否则返回
FeedbackHandler.ResetState() 会停用正向和负向按钮的填充视觉效果,使按钮恢复为中性状态。反馈按钮仅与角色消息气泡相关——玩家气泡不会获得交互 ID。
使用示例
安全培训——用于课后审阅的聊天历史
一个工作场所安全培训模拟使用聊天历史,以便学员在完成场景后回顾完整的 AI 教员对话:
拖拽
TranscriptUI_Chat.prefab到场景中Canvas将
fadeDuration设置为0.3以便在进行中的场景中实现响应式过渡调用
ChatTranscriptUI.ClearAll()在新场景开始时这样做,以免旧消息被带入
在运行时,学员可以看到 AI 教员说过的所有内容的持久记录,并在继续到下一个模块之前,在讲解回顾中滚动查看。
医疗模拟——用于干净叠加层的字幕
一个程序化医疗模拟使用字幕,因此 AI 患者的语音会作为一个干净的叠加层显示在患者模型上方,而不会遮挡屏幕上的临床读数:
将
SubtitleTranscriptUI使用subtitleContainer锚定在底部居中将
autoHideDelay设置为2.0——患者回应之间的快速清除可保持屏幕整洁将
filterBySpeakerType关闭,这样患者和学员的语音都会作为字幕显示
在运行时,每次患者回应都会短暂以字幕形式出现并清除,不会累积历史,从而在整个流程中保持模拟界面整洁。
博物馆信息亭——字幕和历史同时运行
自然历史博物馆为游客运行一个展区屏幕,并为讲解员运行一个单独的审阅站点,两者都由同一段对话驱动:
将
SubtitleTranscriptUI到展区屏幕的Canvas,并将filterBySpeakerType开启且speakerType设置为角色,这样只有展区角色的语音会成为字幕将
TranscriptUI_Chat.prefab到讲解员站点的Canvas两者都从同一个
ConvaiManager.ActiveManager.Transcripts读取并独立更新——无需按模式进行配置
在运行时,游客会在展区看到整洁滚动的字幕,而讲解员站点则会累积完整对话供审阅,全部来自一次会话。
故障排除
[ChatTranscriptUI] chatContainer 未分配 - 消息将不会显示
chatContainer 未在检查器中连接
分配 RectTransform 消息气泡应作为其父对象的
[ChatTranscriptUI] scrollRect 未分配 - 自动滚动将无法工作
scrollRect 未在检查器中连接
分配 ScrollRect 组件;不会自动滚动,但气泡仍会出现
[ChatTranscriptUI] 未找到活动的 ConvaiManager。
ConvaiManager 缺失或尚未初始化
将 ConvaiManager 到场景中,并确保在此组件查找它之前它已完成初始化
[ChatTranscriptUI] 无法发送消息 - 依赖项未注入
在 chatInputField 中输入的文本在依赖项注入之前
确保 ConvaiManager 和一个 ConvaiPlayer 存在于场景中并已初始化
[SubtitleTranscriptUI] 未找到活动的 ConvaiManager。
与上面相同的原因,适用于字幕脚本
将 ConvaiManager 到场景中
字幕从不出现
没有组件在调用 SubscribeCaptions 在场景中,或者字幕的说话者不匹配已配置的过滤器
将 SubtitleTranscriptUI,确认其 TMP_Text 字段已分配,并检查 filterBySpeakerType/speakerIdFilter/participantIdFilter
聊天和字幕显示都不更新
ConvaiTranscripts.IsPresentationEnabled 为 false
检查设置面板的 Transcript 开关,或应用 TranscriptEnabled = true 通过一个 ConvaiRuntimeSettingsPatch
反馈按钮从不高亮
SendFeedback 返回 false
确认你的代码为该轮调用了 ChatMessageBubble.SetInteractionID(string) ——没有任何已发布组件会自动执行此操作
下一步
你已经添加了聊天历史显示、字幕,或两者都添加,并为聊天消息连接了反馈按钮。若要自定义气泡的视觉外观或构建完全自定义的转录显示,请参见“自定义 UI 组件”。若要让用户在运行时显示或隐藏转录显示,请参见“设置面板”。
最后更新于
这有帮助吗?