6.7 KiB
6.7 KiB
条件交互与消耗型交互(技术参考)
更多“条件/消耗/解锁/UI 提示/指向高亮”的统一说明见:
目的
在不改动现有 IInteractable 行为脚本(门/机关/拾取物等)的前提下,为交互调用链增加“资格校验 / 消耗 / 解锁”能力,并通过给场景物体挂载条件组件完成配置。
交互链路(当前项目实现)
- 玩家按下交互键后,
PlayerController.PerformInteract():- Raycast 命中交互层物体
- 收集命中物体与其父物体上的所有
IInteractable - 在调用
Interact()前,查找命中物体父级上的所有InteractConditionBehaviour并逐一CanInteract(...)- 任意条件失败:阻止交互,并输出失败原因
- 全部条件通过:依次调用
IInteractable.Interact()
- 交互成功后,逐一回调
InteractConditionBehaviour.OnInteractSucceeded(...)(用于消耗、解锁等)
相关代码入口:
如何给门/机关配置条件
无条件交互(默认)
- 不挂任何
InteractConditionBehaviour子类组件 - 玩家会直接调用目标上的
IInteractable.Interact()
单条件:需要某个物品(可选消耗/解锁)
挂载组件:RequireItemsInteractCondition
mode = RequireAllrequirements:只填 1 条(requiredItemId+requiredAmount)consumeOnSuccess:成功交互后扣除数量unlockAfterSuccess:成功一次后标记已解锁,后续无需再次校验/消耗unlockState:可选,绑定 InteractUnlockState 用于后续 UI/渲染读取解锁状态failReason:失败提示(可不填)allowIfInventoryMissing:背包系统缺失时是否仍放行(慎用)
多条件(AND):挂多个条件组件
- 同一个门/机关根节点上挂多个
InteractConditionBehaviour子类 - 玩家侧按顺序逐个校验,任意失败都会阻止交互
示例:门需要钥匙 + 玩家饥饿值必须大于 10(后者可由你后续新增一个“玩家状态条件”组件实现)。
多道具条件(OR/AND):一个组件内表达
挂载组件:RequireItemsInteractCondition
modeRequireAll:所有条目都满足才通过(等价 AND)RequireAny:任意一个条目满足就通过(OR)
requirements:配置多个条目(requiredItemId+requiredAmount)consumeOnSuccessRequireAll:依次扣除所有条目数量RequireAny:扣除“触发通过的那一条”的数量
unlockAfterSuccess:同上unlockState:可选,绑定InteractUnlockState作为解锁状态源
解锁状态与外观切换(锁隐藏/电池显示)
挂载组件:InteractUnlockState
unlocked:当前是否解锁(用于初始状态)activateWhenUnlocked:解锁后需要显示/激活的物体(例如发电机上的电池模型)deactivateWhenUnlocked:解锁后需要隐藏/取消激活的物体(例如门锁子物体)- (可选)勾选
blockInteractionWhenLocked:让该组件本身参与“互动条件校验”,未解锁时会直接阻止互动并返回lockedFailReason - (可选)联动事件:可在
onUnlocked / onLocked / onValueChanged(bool)上挂接音效、UI、剧情等
解锁门禁(未解锁时禁止互动)
挂载组件:RequireUnlockedInteractCondition
unlockState:绑定某个InteractUnlockState(未绑定时默认在父级查找)failReason:失败提示- 也可以不挂本条件组件,改为在
InteractUnlockState上勾选blockInteractionWhenLocked达到同样的“未解锁不可互动”效果
交互成功后解锁其它目标(发电机解锁开关)
挂载组件:UnlockStatesOnInteractSucceeded
unlockSelf:是否同时解锁自身(可用于仅通过一次后永久放行)targetStates:需要被解锁的其它InteractUnlockState(例如某个开关的解锁状态)
指向高亮(外轮廓发光)
该效果用于“玩家指向可交互对象时显示外轮廓”,并按可互动/被锁定显示不同颜色。
- 给可交互对象挂载:InteractOutlineTarget
- 默认会自动查找子物体 Renderer;也可手动指定
renderers
cameraTransform / interactRange / interactLayer与交互射线保持一致outlineMaterial:使用Project/InteractOutlineShader 创建的材质canInteractColor:可直接互动颜色(默认偏绿)lockedColor:需要解锁颜色(默认偏橙)
- Shader 资源:
Assets/_Project/Shaders/InteractOutline.shader(Shader 名称:Project/InteractOutline)
推荐的挂载位置
- 推荐将条件组件挂在“门/机关根节点”上(通常是 collider 的父物体或同一层级)
- 玩家侧通过
GetComponentsInParent<InteractConditionBehaviour>()获取,因此挂在父级更稳妥
失败原因与 UI
- 当前失败原因会在玩家侧以日志输出(来自条件组件的
failReason或自动生成) - 如果后续要接 UI 提示,建议从
PlayerController的“条件失败分支”作为统一出口对接(而不是散落在每个交互脚本里)
注意事项
- 条件校验与消耗均基于
ItemData.id(string),请确保 id 唯一且稳定 unlockAfterSuccess的解锁状态是运行期内存状态;如果你需要跨存档持久化,建议后续接入存档系统再把“已解锁”写入存档