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