For the complete documentation index, see llms.txt. This page is also available as Markdown.

编写自定义执行器

实现 IConvaiActionExecutor 以创建您的项目所需的任何行为——包含完整示例、取消处理和复合操作模式。

何时编写自定义执行器

Convai SDK 中包含的执行器覆盖了常见场景,但每个项目都有独特的行为需求。在以下情况编写自定义执行器:

  • 你的游戏使用自定义移动系统(角色控制器、物理系统、寻路库)

  • 你需要与 UI 系统、库存、物理对象或外部服务交互

  • 你想通过条件逻辑组合多个行为

  • 内置执行器无法满足你的 NPC 所需的精确行为

自定义执行器其实只是 C# 类 ——一个实现了一个接口的 MonoBehaviour。除此之外没有任何 SDK 专属样板代码。


IConvaiActionExecutor 接口

任何实现 IConvaiActionExecutor 的 MonoBehaviour 都可用作执行器。

using System.Threading;
using System.Threading.Tasks;
using Convai.Runtime.Actions;

public interface IConvaiActionExecutor
{
    Task<ConvaiActionExecutionResult> ExecuteAsync(
        ConvaiActionInvocation invocation,
        CancellationToken cancellationToken);
}

该方法是 异步 的。你可以 等待 协程、任务或任何异步操作。


调用对象

ConvaiActionInvocation 会传入 ExecuteAsync ,并包含运行该行为所需的一切:

属性
类型
描述

命令

ConvaiActionCommand

来自后端的原始命令: Command.NameCommand.Target (尚未解析的目标名称字符串)。

定义

ConvaiActionDefinition

你的本地动作定义: Definition.ActionName, Definition.TimeoutSeconds,等等。

解析后的目标

ConvaiResolvedActionTarget

匹配到的目标。 ResolvedTarget.GameObjectReference 会为你提供场景中的 GameObject。

Character

ConvaiCharacter

执行此操作的角色。

批次索引

int

此次调用属于哪个批次(从 0 开始)。

步骤索引

int

这是该批次中的第几步(从 0 开始)。

获取目标的场景 GameObject:


返回结果

请从以下工厂方法中返回其中之一: ConvaiActionExecutionResult:

方法
何时使用

ConvaiActionExecutionResult.Succeeded()

操作已成功完成。

ConvaiActionExecutionResult.Failed(string message, Exception ex)

出现了问题(缺少组件、无效状态等)。消息和异常为可选项。

ConvaiActionExecutionResult.Unhandled(string message)

此执行器无法处理给定的调用(例如,目标类型错误)。分发器会触发 OnStepUnhandled。消息为可选项。

ConvaiActionExecutionResult.Canceled()

该操作已取消(通常因为你检测到 cancellationToken.IsCancellationRequested).

ConvaiActionExecutionResult.TimedOut()

TimeoutSeconds 超出时限时由分发器自动返回——你无需手动返回它。


取消与超时

ExecuteAsync 接收一个 CancellationToken。当以下情况发生时,该令牌会被取消:

  • 批次被取消(例如, ReplaceCurrent 策略接收到新批次)

  • 该操作的 TimeoutSeconds 到期

如果你的执行器运行循环或等待长时间运行的操作, 请检查令牌 以避免无限期阻塞:

或者直接将令牌与 等待 一起使用—— OperationCanceledException 会被分发器自动捕获:


分步:构建一个“高亮对象”执行器

本示例构建一个 HighlightObjectExecutor 它会在触发时为目标对象启用轮廓/高亮组件,等待三秒,然后将其禁用。

1

创建脚本

创建一个名为以下内容的新 C# 文件: HighlightObjectExecutor.cs 放到你的项目中:

2

将组件添加到你的 NPC

选中你的 NPC 的 GameObject,然后点击 添加组件 → My Game → Highlight Object Executor.

高亮持续时间 设置为你想要的值(默认:3 秒)。

3

将其连接到动作定义

ConvaiActionConfigSource 在同一个 NPC GameObject 上:

  1. 动作定义.

  2. 动作名称 设为 高亮 (或你使用的任何名称)。

  3. 目标要求 设为 对象.

  4. HighlightObjectExecutor执行器 字段从另一个 GameObject 分配角色。

4

测试它

Play 并对角色说:

“高亮灭火器。”

灭火器上的 Outline 组件应启用三秒,然后禁用。


更简单的示例:传送执行器

供参考,这是最小的自定义执行器模式——没有异步等待,只有同步操作:

注意使用 Task.FromResult ——对于同步执行器,请包装结果,而不是使用 异步/等待.


复合执行器模式

对于由多个游戏步骤组成的操作,请将整个序列放入一个 ExecuteAsync。分发器会将一个动作定义视为一个不可分割的单元——它会等待你的任务完成后再开始下一步。

参见 PickUpActionExecutor 在 SDK 中查看该模式的完整参考实现。


提示与最佳实践

返回 未处理 当此执行器不是合适的任务处理器时。 例如,如果你的执行器只处理生物目标,却收到了一个对象目标,请返回 未处理 而不是 失败。这样其他执行器(或回退方案)就可以处理该步骤,而不会被计为失败。

返回 失败 对于真正的错误 ——缺少组件、空引用、无效状态。请附上描述性消息,以便调试探针和控制台日志帮助你诊断问题。

执行器运行在 Unity 主线程上。 你可以安全地访问 transform, GetComponent, Instantiate以及其他 Unity API,而无需进行跨线程封送。

只要游戏玩法工作仍在进行,就让任务保持活跃。 分发器会等待 ExecuteAsync 返回后才会开始下一步。对于寻路之类的长时间运行操作,请在执行器内部保持循环运行,直到工作真正完成。


结论

自定义执行器只是一个只有一个方法的 MonoBehaviour。实现 IConvaiActionExecutor,从以下位置获取目标: invocation.ResolvedTarget.GameObjectReference,完成你的工作,然后返回结果。对于长时间运行的行为,请使用 异步/等待 并检查 CancellationToken 以遵守超时和策略取消。

最后更新于

这有帮助吗?