角色动作的工作原理
了解 Convai 角色动作如何从会话设置进入排队的 Blueprint 处理器执行,并完成报告。
角色动作将 Convai 所说内容与角色在关卡中实际执行的行为连接起来。当玩家说话时,Convai 可以同时返回一段口头回复和一串命名动作——前往某个地点、跟随玩家、与对象交互。插件会将这些动作分发到 NPC Actor 上对应的 Blueprint 处理函数事件,并按顺序一次执行一个。
所需设置
Convai 聊天机器人 组件
所有动作
携带 环境 属性(动作模板、对象、角色)以及 ActionsQueue.
Convai Player 组件
所有动作
玩家 Pawn 上用于语音输入所必需。
Blueprint 处理函数
每个应执行的动作
每个动作名对应一个函数,接收 FConvaiResultAction.
NPC Actor 上的 AI Controller
移动动作(移动到, 跟随)
所需用途 AI Move To 才能工作。使用 Unreal 内置的 AIController.
Nav Mesh Bounds Volume (内置)
移动动作
必须覆盖 NPC 生成点和所有导航目标。关卡变更后请重新构建。
对于非移动动作(自定义行为、动画、状态变化),只需要聊天机器人组件和 Blueprint 处理函数。
关键概念
六个概念支撑着系统的工作方式。下面每一节都会详细介绍其中一个,但这里先给出一个快速概览:
动作契约
会话开始前发送给 Convai 的动作、对象和角色列表——定义了角色被允许执行和引用的内容。
动作流水线
两条并行通道:一条播放语音音频,另一条按顺序存储并执行一串动作。
队列与分发
插件会维护一个待处理动作队列。每次处理器报告完成后,队列前进一个位置,并运行下一个处理器。
完成模型
每个处理器在完成时都必须调用 HandleActionCompletion 。如果没有这次调用,队列就会停滞,后续动作也不会运行。
等待语音门控
一个可选的按动作设置的标志,它会在角色开始说话或说完之前延迟触发该动作,使移动与语音保持同步。
运行时变更
对象和角色可以在会话进行时添加或移除;本地环境会立即更新。
动作契约
会话开始前,聊天机器人组件会读取 环境 属性——其中包含动作模板、已注册对象和角色列表——并将这些信息发送给 Convai。Convai 会据此了解角色可以执行哪些动作,以及在响应玩家语音时可引用哪些对象。
该契约包含三部分:
动作 ——一个有序的
FConvaiAction模板,每个模板都有名称、可选描述以及可选的带类型参数。该列表定义在环境的属性中UConvaiChatbotComponent,位于动作字段。对象 ——一个
FConvaiObjectEntry数组,其中的值用于描述可交互的场景对象。每个条目都有一个名称,一个可选的描述,以及导航目标字段。角色 ——一个
FConvaiObjectEntry用于描述场景中其他角色的值。
该 启用动作 切换开启 Convai 聊天机器人 组件的 环境 属性充当总开关。它默认设为 true ,适用于每个新组件,因此该功能开箱即用即启用。禁用后,契约不会在会话开始时发送,角色会表现为纯对话型 NPC。
动作流水线
当玩家与 Convai 角色对话时,插件会通过两条并行通道处理响应:
语音通道 ——音频流会传送到角色的音频组件进行播放。聊天机器人会触发
收到动作和OnStartedTalking/OnFinishedTalking事件,随着语音进展而触发。动作通道 ——Convai 会根据
action_config契约解析响应,并返回一串FConvaiResultAction结构体。插件将该序列存储在ActionsQueueonUConvaiChatbotComponent.
两条通道彼此独立。语音播放的同时,动作队列也在执行。
队列与分发
插件维护一个 FConvaiResultAction 条目队列,存放于 ActionsQueue中。当新的动作序列到达时,插件会:
如果队列中已经有一个正在进行的动作,就保留第一个动作,并用传入的序列替换其余排队动作。如果队列为空,则原样存储传入的序列。
调用
StartFirstAction,它会从队列中读取第一项并调用TriggerNamedBlueprintAction.TriggerNamedBlueprintAction会查找名称与结果的Action字段匹配的 Blueprint 函数或事件。它会先检查所属 Actor,再检查聊天机器人组件。该处理函数可以接受一个FConvaiResultAction参数,或者不接受参数。
分发器基于名称。Unreal 解析处理器名称时不区分大小写,但空格和标点仍必须匹配。如果在任一目标上都找不到匹配函数,插件会记录警告,处理器不会被调用,队列会停滞,直到 HandleActionCompletion 或 AbortActionSequence 被调用。
取消动作计划
当某个动作仍在运行时,角色可以改变路线——玩家重新引导它,或者新的情况让当前计划变得毫无意义。 CancelCurrentActionPlan on UConvaiChatbotComponent (蓝图显示名称 取消当前动作计划)会以协作方式取消,而不是直接把队列从正在运行的处理器脚下抽走:排队中的动作会立即丢弃,但当前活动处理器会获得一个可选的 Blueprint 事件,名称正好为 Cancel <动作名>,并携带原始的 FConvaiResultAction,以便在替代计划开始前干净地停止其计时器、委托或延迟任务。重复调用只会请求一次取消,并等待一次终态确认。
实现了可选取消事件的处理器必须调用 HandleActionCancellation ,一旦它完全静止下来——也就是在其计时器、委托、任务和回调都停止之后。该调用不报告成功或失败,并会释放所持有的替代计划,使队列能够继续前进。未实现取消事件的处理器则由其自行完成;无论哪种情况,自定义取消处理器都必须且只能调用一个终态 API—— HandleActionCancellation 或者其现有的完成路径——绝不能两者都调用。
启用 bEnableCancelActionPlanAction (蓝图显示名称 启用取消动作计划,类别 Convai|Actions|Experimental)在聊天机器人组件上会添加一个保留的 取消动作计划 控制动作到发送给 Convai 的契约中,因此当玩家重新引导或放弃角色正在执行的事情时,角色本身可以决定是否调用取消。参见 配置动作 了解该切换项,以及 动作蓝图参考 查看完整的函数和事件列表。
等待语音门控
FConvaiAction 都有一个 bWaitForBotSpeech 标志。当它设置在某个动作模板上,且该动作作为新接收序列中的第一个动作到达时(即序列到达时队列为空),插件会延迟启动该动作,直到 Convai 开始说话(OnStartedTalking)或说完(OnFinishedTalking),以先触发者为准。每个角色的超时(ActionWaitForBotSpeechTimeoutSec,默认 2.0 秒,不对 Blueprint 暴露)会在两种语音事件都未及时到达时仍然触发该动作。
一个可选的 DelayAfterBotSpeechSec 字段会在语音条件满足后再额外增加延迟。
完成模型
处理器负责报告结果。处理器完成工作后,必须调用 HandleActionCompletion 位于 UConvaiChatbotComponent:
IsSuccessful = true——插件会将当前动作出队并开始下一个。IsSuccessful = false——插件会清空剩余队列。角色不会尝试下一个动作。
当 bAutoReport 为 true (默认),插件还会向 Convai 发送一条描述结果的上下文事件。Convai 会在生成角色下一次口头回复时使用这些信息。
如果处理器遇到无法恢复的错误,并希望 Convai 生成一个全新的动作计划,它会调用 AbortActionSequence ,并可选地传入一段关于出错原因的文本说明。
下图展示了一个从开始到完成的单动作交互。当序列包含多个动作时,每次 HandleActionCompletion(true) 调用都会让队列前进一步。
运行时环境变更
可在运行时使用 AddObject, RemoveObject, AddCharacter,以及 RemoveCharacter 上的一组方法 UConvaiChatbotComponent向本地环境添加或移除对象和角色。本地 EnvironmentData 镜像会立即反映这些变化,并在插件解析后续动作结果时使用。
运行时变更不会改变动作集本身,动作集在下次重新连接之前保持固定。对于实时会话,场景上下文更新会通过 update-scene-metadata 在变更的条目尚未包含在连接时的场景元数据快照中时发送。
下一步
配置动作内置动作处理器构建自定义动作处理器动作 Blueprint 参考最后更新于
这有帮助吗?