会话生命周期
了解 ConvaiCharacter 会话如何在状态之间转换、会话 ID 存储在哪里,以及如何配置重连和恢复对话行为。
每个 ConvaiCharacter 场景中的都与 Convai 保持一个独立会话。该会话会跟踪角色是否已连接、当前状态是什么,以及——在启用持久化时——你上次连接时处于哪段对话。理解会话如何创建、持久化和恢复,可以让你在训练模拟、交互式体验和游戏中构建可靠、可恢复的角色交互。
会话状态机
每个角色会话会经历以下状态。
未连接
0
没有活动会话。初始状态,以及正常断开后的最终状态。
连接中
1
连接尝试进行中。从未连接过渡到已连接。
Connected
2
会话处于活动状态。音频流和对话都在运行。
重新连接中
3
连接已丢失。SDK 正在尝试自动重新建立连接。
正在断开连接
4
正在进行优雅关闭。从已连接过渡到未连接。
错误
5
不可恢复的错误。需要人工干预才能重新连接。
你会通过以下方式接收状态转换: SessionStateChangedRelayData 事件,通过 ConvaiSessionEventRelay。参见 事件系统 来了解如何订阅。
按角色的会话
每个 ConvaiCharacter 都有自己独立的会话。会话不会在角色之间共享。在多角色场景中,每个角色都会独立连接和断开——会话 ID 绑定到 Inspector 中设置的角色 ID 字符串(而不是场景名或对象名),重连策略按角色生效,并且某个角色上的会话错误不会影响其他角色。
ConvaiSessionData 是持久化会话存储,它将每个角色映射到其当前会话标识。它会在启动时自动从磁盘加载,并在每次更改时写入到 {Application.persistentDataPath}/Convai/sessions.json ——会话 ID 无需任何额外设置即可在应用重启后保留。
GetSessionId(characterId)
返回该角色当前的会话 ID,或者 null (如果不存在)。
StoreSessionId(characterId, sessionId)
为该角色存储一个会话 ID,并立即保存到磁盘。
ClearSessionId(characterId)
移除某个角色的会话 ID 并保存。
ClearAllSessionIds()
移除所有已存储的会话 ID 并保存。
GetAllSessionIds()
返回所有当前角色→sessionId 映射的只读快照。
ConvaiSessionData 是一个单例。数据存储在 {Application.persistentDataPath}/Convai/sessions.json ,并在应用重启后持续保留。如果你需要从头开始,请显式调用 ClearAllSessionIds() 。
会话持久化
当会话 ID 被持久化后,SDK 可以在下一次连接时恢复之前的对话——角色会记住先前交互的上下文。
哪些会持久化,哪些会重置
会话 ID
通过以下方式持久化: ConvaiSessionData ——支持恢复
对话历史
由 Convai 管理;当会话 ID 有效时会恢复
进行中的音频
重置——任何流中的音频都会被丢弃
活动轮次状态
重置——该轮次会重新干净开始
模块状态(例如情绪)
重置——模块会在重连时重新初始化
默认持久化栈
SDK 通过以下方式提供可插拔的持久化层: ISessionPersistence ,适用于需要自定义后端存储的项目(加密存储、云存档、数据库)。默认栈如下:
会话 ID 以如下格式的键存储: convai.session.<characterId>.
替换持久化存储
实现 IKeyValueStore 即可使用任何后端存储——数据库、加密存储、云存档系统。 PlayerPrefsKeyValueStore 会在内部将所有读写调度到 Unity 主线程;如果你的后端存储有线程限制,也请采用同样的线程安全模式。
通过以下方式注册: ConvaiRuntimeBuilder:
重连策略
ReconnectPolicy 控制当连接意外断开时 SDK 的行为。
RoomRejoinTtlSeconds
double
60
SDK 在断开后可以重新加入现有房间的时间窗口(秒)。超过该窗口后,会创建一个新房间。
ResumePolicy
ResumePolicy
ResumeIfPossible
控制 SDK 是否尝试通过以下方式恢复之前的对话: character_session_id.
MaxReconnectAttempts
int
3
在会话进入以下状态之前允许的自动重连最大次数: 错误 状态的聊天机器人。
SpawnAgentOnRejoin
bool
true
重新加入现有房间时是否重新生成 AI 代理。
StartWaitTimeoutMs
int
5000
连接 Start() 阶段在被视为失败之前的超时时间(毫秒)。
AutoMicStartDelaySeconds
float
0.5
连接后等待多长时间再启动麦克风(秒)。可防止在会话完全就绪前捕获音频。
ResumePolicy 选项
ResumePolicy 选项AlwaysFresh
始终开启全新对话。角色不会记住上一个会话。
ResumeIfPossible
尝试恢复之前的对话。如果会话已过期或恢复失败,则回退到全新会话。
AlwaysResume
始终恢复。如果恢复失败,连接就会失败——不会回退到全新会话。
预设策略
ReconnectPolicy.Default
60 秒 TTL, ResumeIfPossible,3 次尝试,麦克风延迟 0.5 秒
ReconnectPolicy.AlwaysCreateNew
不尝试重新加入。始终创建新房间和全新会话。
AlwaysResume 会将会话置于 错误 状态,如果 Convai 无法恢复会话(例如会话已在后端过期)。除非你的训练模拟要求严格连续性,并且你已经明确处理了错误状态,否则请使用 ResumeIfPossible 。
使用示例
示例 1:医疗训练模拟——网络中断后恢复
学习者正在评估中途时网络中断。连接恢复后,患者角色会恢复同一段对话——不会丢失上下文。
预期结果: SDK 会在 2 分钟窗口内自动重试最多 5 次。如果 Convai 端的会话仍然有效,对话会从中断处继续。如果会话已过期,角色会开启一段全新对话,而不是卡住。
示例 2:企业入职自助终端——始终全新的对话
每位接近终端的新员工都应从头开始,并且不记得之前的用户。 AlwaysFresh 和 AlwaysCreateNew 确保每次都从干净状态开始。
为了确保在下一次会话开始前移除前一位用户的数据:
预期结果: 每位新用户都会开始一段完全全新的对话。角色不会记住之前的交互,这对于共享自助终端部署是正确的。
示例 3:在训练模拟中处理错误状态
当所有重连尝试都用尽后,会话会进入 错误 状态。应将其呈现给培训主持人,并允许手动重试,而不是静默卡住。
预期结果: 当会话进入 错误 状态时,错误面板会出现。培训主持人点击“重试”,即可在不重启模拟的情况下尝试新的连接。
故障排查
会话在断开后一直停留于 错误 状态
AlwaysResume 无法在后端恢复已过期的会话
切换为 ResumeIfPossible;调用 ClearSessionId(characterId) 以移除陈旧的会话 ID,然后重新连接
尽管 ResumeIfPossible
之前的 ClearAllSessionIds() 调用清空了会话文件,或者运行之间角色 ID 发生了变化
请验证 characterId 字符串在各次运行之间保持稳定;检查 {persistentDataPath}/Convai/sessions.json
会话一直卡在 连接中 状态,永远不变
StartWaitTimeoutMs 未针对慢速网络配置;或防火墙阻止了传输
增加 StartWaitTimeoutMs 在 ReconnectPolicy;验证对 Convai 端点的网络访问
重连循环始终失败;会话最终进入 错误
MaxReconnectAttempts 已耗尽
订阅 ConvaiSessionEventRelay.OnSessionStateChanged 并将错误展示给用户;在用户确认后手动调用重连
两个角色共享了同一个会话 ID
Inspector 中的角色 ID 字符串相同
为每个角色分配唯一的角色 ID ConvaiCharacter 在场景中
下一步
现在你已经了解角色会话如何创建、状态转换如何工作、会话 ID 如何在重启间持久化,以及如何配置重连行为。接下来阅读轮次切换模式,了解 SDK 如何检测语音输入,然后阅读事件系统,学习如何在场景脚本中订阅会话和角色事件。
最后更新于
这有帮助吗?