总览
如果你不是在做 Mass 人群,最常见的接入方式有三种:蓝图直接调 SmartObjectSubsystem,C++ 写自己的交互任务,Behavior Tree 用 EQS 找点再执行行为。哪种都可以,但生命周期必须一致:Find 只是候选,Claim 才是占位,Occupied 才是使用,结束必须 Free。
蓝图路径
蓝图里通常这样拆:AI 触发“找椅子”事件,构造请求范围和 Filter,调用 Find Smart Objects,选一个结果,Claim,MoveTo Slot Transform,开始行为,行为结束释放。蓝图适合做验证和简单 AI,但生产项目建议把 Claim/Release 封成 C++ 节点,避免每个蓝图都漏 Abort 清理。
C++ 路径
C++ 最适合写通用 UAITask 或 UAbilityTask。任务持有 FSmartObjectClaimHandle,在 Activate 里查询和 Claim,在 MoveTo 成功后 Occupy,在 OnDestroy 或 Cancel 里释放。这样不管行为树 Abort、能力取消还是角色死亡,清理都能进同一条路径。
void UMyUseSmartObjectTask::AbortAndRelease()
{
if (ClaimHandle.IsValid())
{
if (USmartObjectSubsystem* Subsystem = USmartObjectSubsystem::GetCurrent(GetWorld()))
{
Subsystem->MarkSlotAsFree(ClaimHandle);
}
ClaimHandle.Invalidate();
}
}
EQS 路径
UEnvQueryGenerator_SmartObjects 会从 Query Origin 出发,用 QueryBoxExtent 找 Smart Object Slot。配置 SmartObjectRequestFilter 后,你可以继续用 EQS 的距离、路径、可见性测试排序。它有 bOnlyClaimable,适合过滤掉已经不可 Claim 的 Slot。
EQS 的好处是策略清晰:Smart Object 负责“哪些点合法”,EQS 负责“哪个点最好”。比如找掩体时,Smart Object 只筛出 Activity.Cover,EQS 再按敌人方向、路径长度、遮挡质量排序。
Behavior Tree 路径
UBTTask_FindAndUseGameplayBehaviorSmartObject 是开箱即用的 BT Task。它有 ActivityRequirements、ClaimPriority、EQS 请求和 Fallback Radius。任务会查找 Smart Object,并用 UAITask_UseGameplayBehaviorSmartObject 执行对应 GameplayBehavior。
如果你希望自己控制 MoveTo、朝向、动画和释放,更建议拆成三个 BT Task:FindAndClaim、MoveToSmartObject、UseAndRelease。这样每一步都能在黑板上看见 ClaimHandle、Slot Transform 和失败原因。
使用案例
守卫下班流程:Behavior Tree 进入 Rest 分支,EQS 找 Activity.Sit,Claim 椅子,MoveTo 椅子入口,执行 GameplayBehavior 坐下。收到警报时 BT Abort,任务释放 Claim,守卫切回警戒。这个案例能覆盖查询、占用、中断和行为执行。
架构分析
Behavior Tree 版本把很多细节封装了,适合上手;C++ 版本可控性高,适合项目统一封装;EQS 版本适合做“多候选排序”。三者不是互斥关系。一个成熟项目常常是:EQS 做候选,C++ Task 统一生命周期,BT/StateTree 负责决策。
项目落地
给 AI 程序提供一个统一组件或库:FindSmartObjectByActivity、ClaimSmartObject、GetClaimedSlotTransform、UseSmartObject、ReleaseSmartObject。蓝图只调用高层节点,不直接拼 Subsystem 的所有细节。
常见坑
- BT Task Abort 不释放:这是最常见的“椅子被占死”来源。
- EQS 只排序不 Claim:EQS 结果只是候选。
- Blackboard 保存 RequestResult 而不是 ClaimHandle:跨帧使用需要 ClaimHandle。
- MoveTo 目标用对象 Actor Location:应该用 Slot 或 Entrance Transform。
- 客户端蓝图直接改状态:多人项目里占用和释放应由服务器主导。
源码依据
UEnvQueryGenerator_SmartObjects 提供 EQS Generator,参数包括 QueryOriginContext、FSmartObjectRequestFilter、QueryBoxExtent 和 bOnlyClaimable。UBTTask_FindAndUseGameplayBehaviorSmartObject 保存 ActivityRequirements、ClaimPriority、EQSRequest 和 Fallback Radius。UBlackboardKeyType_SOClaimHandle 提供黑板 ClaimHandle 类型。
源码路径索引
SmartObjectsModule/Public/SmartObjectBlueprintFunctionLibrary.hSmartObjectsModule/Public/EnvQueryGenerator_SmartObjects.hSmartObjectsModule/Public/BlackboardKeyType_SOClaimHandle.hGameplayBehaviorSmartObjectsModule/Public/AI/BTTask_FindAndUseGameplayBehaviorSmartObject.hGameplayBehaviorSmartObjectsModule/Public/AI/AITask_UseGameplayBehaviorSmartObject.h