总览
Smart Object 最终都会遇到一个问题:这个对象“平时可用”,但现在不可用。门锁了、工作台坏了、任务没解锁、夜晚不能营业、敌对阵营不能使用、Slot 被临时封住。不要把这些条件散落在 AI 蓝图里,应该让 Smart Object 的查询阶段就能解释它为什么被拒绝。
条件放哪里
| 条件 | 推荐位置 | 例子 |
|---|---|---|
| 整个对象不可用 | Definition Preconditions 或实例 RuntimeTags | 门锁、摊位关门 |
| 某个 Slot 不可用 | Slot SelectionPreconditions 或 SetSlotEnabled | 左侧工位维修 |
| 用户资格 | UserTagFilter | 只有 User.Player 能开门 |
| 临时禁用 | SetEnabledForReason / SetSlotEnabled | 任务禁用、战斗禁用 |
| 复杂世界状态 | World Conditions | 时间、任务、阵营、全局变量 |
使用案例
门锁案例:门的 Definition 有 Activity.Door.Open。默认可查找,但 World Condition 检查门 Actor 是否含 SO.State.Locked 或玩家是否持有 Item.Key.Red。锁住时查询阶段直接拒绝;如果玩家拿到钥匙,条件通过,AI 或玩家才会 Claim。
工作台维修案例:对象仍然可见,但 Craft_Left Slot 被禁用。使用 SetSlotEnabled 或给 Slot 加 RuntimeTag SO.State.Broken,并让 Slot Condition 检查该 Tag。这样另一个 Slot 仍可用,不必禁用整个对象。
架构分析
USmartObjectDefinition 有对象级 Preconditions,FSmartObjectSlotDefinition 有 Slot 级 SelectionPreconditions。条件执行需要 USmartObjectWorldConditionSchema 提供上下文。源码里提供了 Actor Tag、Object Tag、Slot Tag 等 WorldCondition 类型:它们让条件能读对象、Slot、用户数据或 Actor 标签。
运行时还有 Enabled reason。USmartObjectSubsystem::SetEnabledForReason 和组件上的 K2_SetSmartObjectEnabledForReason 用 FGameplayTag 表示禁用原因。源码里默认 reason 是 SmartObject.EnabledReason.Gameplay。这个机制适合临时禁用整个对象,并且能调试“到底是谁禁用了它”。
项目落地
建立一张“条件归属表”:任务进度、阵营、日夜、对象损坏、占用、战斗禁用分别由谁维护。不要让 Smart Object 条件直接访问一堆单例;优先用 Tag、组件接口或轻量上下文数据。条件越可解释,AI 排查越快。
常见坑
- 把所有动态状态都塞到 UserTagFilter:UserTagFilter 是用户资格,不是世界状态。
- 用 Disable 整个对象解决 Slot 问题:会误伤其他 Slot。
- 条件太重:查询可能很频繁,条件里不要做复杂寻路或资产加载。
- 客户端条件和服务器条件不一致:多人项目里服务器判定必须权威。
- 没有调试命名:
State.A不如SO.State.LockedByQuest。
源码依据
USmartObjectDefinition 保存 FWorldConditionQueryDefinition Preconditions,Slot 保存 SelectionPreconditions。FSmartObjectRequestFilter 的 bShouldEvaluateConditions 控制是否评估条件。USmartObjectSubsystem 提供 FilterSlotsBySelectionConditions、FilterResultsBySelectionConditions 和 EvaluateSelectionConditions。WorldCondition 相关类包括 USmartObjectWorldConditionSchema、FSmartObjectWorldConditionObjectTagQuery、FSmartObjectWorldConditionSlotTagQuery 和 FWorldCondition_SmartObjectActorTagQuery。
源码路径索引
SmartObjectsModule/Public/WorldConditions/SmartObjectWorldConditionSchema.hSmartObjectsModule/Public/WorldConditions/SmartObjectWorldConditionObjectTagQuery.hSmartObjectsModule/Public/WorldConditions/SmartObjectWorldConditionSlotTagQuery.hSmartObjectsModule/Public/WorldConditions/WorldCondition_SmartObjectActorTagQuery.hSmartObjectsModule/Public/SmartObjectSubsystem.h