c14c63f30d
- Character: 替换UInteractionManager为UInteractionPromptComponent - GameInstance: 空壳化,持久数据迁移至PersistenceSubsystem - InteractionManager: 重写为普通C++ FInteractionManager - InteractableComponent: 碰撞回调接入ASystemDriver注册 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
136 lines
4.6 KiB
C++
136 lines
4.6 KiB
C++
// ChildHood Project - 交互管理器(v1.1 Effect/Action 架构重写)
|
||
// 对应技术方案: docs/technical/交互系统-技术方案.md 第3节(类设计)+ 第6节(行为规则实现)
|
||
// 职责:检测列表维护、选中管理、顶层状态(Free/Executing)
|
||
// 架构:普通 C++ 类(非 UObject、非 UActorComponent),由 ASystemDriver 值持有
|
||
// 特点:纯事件驱动无 Tick,所有变化由外部调用触发
|
||
|
||
#pragma once
|
||
|
||
#include "CoreMinimal.h"
|
||
#include "InteractionTypes.h"
|
||
|
||
class UInteractableComponent;
|
||
class ACharacter;
|
||
|
||
/**
|
||
* FInteractionManager
|
||
*
|
||
* 普通C++类,负责交互检测列表维护和顶层状态管理。
|
||
* 由 ASystemDriver 值持有,不参与 UE 反射系统。
|
||
*
|
||
* 数据流:
|
||
* InteractableComponent 碰撞回调 → ASystemDriver → RegisterInteractable/UnregisterInteractable
|
||
* Character 输入回调 → ASystemDriver → BeginInteract/CancelInteract/SwitchTarget
|
||
* EffectManager 完成回调 → ASystemDriver → OnInteractionFinished
|
||
*/
|
||
class FInteractionManager
|
||
{
|
||
public:
|
||
|
||
/** 初始化管理器,绑定玩家角色引用 */
|
||
void Initialize(ACharacter* PlayerCharacter);
|
||
|
||
// === 交互物注册(由 InteractableComponent 碰撞回调通过 ASystemDriver 调用)===
|
||
|
||
/**
|
||
* 注册交互物到检测列表。
|
||
* 添加后按水平距离排序,重置选中索引为0,刷新缓存。
|
||
*/
|
||
void RegisterInteractable(UInteractableComponent* Interactable);
|
||
|
||
/**
|
||
* 从检测列表注销交互物。
|
||
* Executing 状态下如果移除的是 CurrentInteractable,仅从列表移除,
|
||
* CurrentInteractable 延迟清理(因为 Effect 可能仍在执行)。
|
||
*/
|
||
void UnregisterInteractable(UInteractableComponent* Interactable);
|
||
|
||
// === 交互触发(Character 输入回调中调用)===
|
||
|
||
/**
|
||
* 发起交互(E键触发)。
|
||
* 前置检查:State==Free、SelectedIndex有效、!IsConsumed()。
|
||
* 成功后 State=Executing,返回选中的 Component。
|
||
* 拒绝则返回 nullptr。
|
||
*/
|
||
UInteractableComponent* BeginInteract();
|
||
|
||
/**
|
||
* 取消交互(ESC/E键在Executing阶段触发)。
|
||
* v0.1 简化:仅设置状态标记,实际取消由 ASystemDriver 协调 EffectManager。
|
||
*/
|
||
void CancelInteract();
|
||
|
||
/**
|
||
* 切换选中目标(Tab/滚轮)。
|
||
* Direction: +1下一个 / -1上一个,循环。
|
||
* 仅在 Free 状态下响应。
|
||
*/
|
||
void SwitchTarget(int32 Direction);
|
||
|
||
// === 状态查询 ===
|
||
|
||
/** 获取当前顶层状态 */
|
||
EInteractionState GetState() const { return State; }
|
||
|
||
/** 当前是否有有效的选中交互物 */
|
||
bool HasSelection() const { return CachedSelected.bHasSelection; }
|
||
|
||
/** 获取选中交互物的提示文本(从缓存读取,不访问 Component) */
|
||
FString GetSelectedPromptText() const { return CachedSelected.PromptText; }
|
||
|
||
/** 获取选中交互物的世界坐标(从缓存读取) */
|
||
FVector GetSelectedWorldPosition() const { return CachedSelected.WorldPosition; }
|
||
|
||
/** 获取完整的选中信息缓存 */
|
||
const FSelectedInfo& GetCachedSelectedInfo() const { return CachedSelected; }
|
||
|
||
// === Effect 完成回调(由 EffectManager 通过 ASystemDriver 调用)===
|
||
|
||
/**
|
||
* Effect 执行完毕回调。
|
||
* State 回到 Free,清理 CurrentInteractable,通知 Character 解除交互,
|
||
* 重新排序和刷新缓存(因为消耗可能改变了列表)。
|
||
*/
|
||
void OnInteractionFinished();
|
||
|
||
// === 当前交互物访问(EffectManager 需要访问)===
|
||
|
||
/** 获取当前正在交互的交互物(Executing 状态下有效) */
|
||
UInteractableComponent* GetCurrentInteractable() const;
|
||
|
||
private:
|
||
|
||
/** 交互系统顶层状态 */
|
||
EInteractionState State = EInteractionState::Free;
|
||
|
||
/** 当前附近的交互物列表,按水平距离排序 */
|
||
TArray<TWeakObjectPtr<UInteractableComponent>> NearbyInteractables;
|
||
|
||
/** 当前选中的交互物索引(NearbyInteractables 中的下标) */
|
||
int32 SelectedIndex = 0;
|
||
|
||
/** 当前正在交互的交互物(Executing 状态下锁定) */
|
||
TWeakObjectPtr<UInteractableComponent> CurrentInteractable;
|
||
|
||
/** 玩家角色弱引用(用于排序距离计算和 SetInteracting 调用) */
|
||
TWeakObjectPtr<ACharacter> PlayerCharacter;
|
||
|
||
/** Presentation 层缓存数据 — 选中交互物的摘要信息 */
|
||
FSelectedInfo CachedSelected;
|
||
|
||
// === 内部方法 ===
|
||
|
||
/**
|
||
* 更新选中交互物:按与玩家的水平距离排序,重置 SelectedIndex=0。
|
||
* 同时清理已失效的弱引用。
|
||
*/
|
||
void UpdateSelection();
|
||
|
||
/**
|
||
* 从 Component 读取选中项信息并写入 CachedSelected。
|
||
* Presentation 层每帧只读 CachedSelected,不直接访问 Component。
|
||
*/
|
||
void RefreshCachedSelection();
|
||
};
|