fix(interaction): 修复SetInteracting双调用等4个审查退回问题
对应 Issue #32 审查退回(第二次)的4个问题: 1.(重大)移除 InteractionManager 反射调用 SetInteracting,SetInteracting(false) 改由 SystemDriver.OnEffectComplete 协调触发 2.(重大)DoorActor::OnInteractStarted 改为空实现,门开关业务由 EffectManager::ExecuteToggleDoor 驱动 3.(中等)EffectManager::ExecuteCameraReturn 销毁 PushCam 并清空 CachedPushCamera,避免冗余回位 4.(中等)EffectManager::AddToBackpack 添加收集系统集成 TODO 注释 编译验证通过 (UE5.7 ChildHoodEditor Development) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -24,11 +24,11 @@ ADoorActor::ADoorActor()
|
||||
|
||||
void ADoorActor::OnInteractStarted_Implementation(UInteractableComponent* Comp)
|
||||
{
|
||||
// 只响应门组件的交互
|
||||
if (UDoorInteractableComponent* DoorComp = Cast<UDoorInteractableComponent>(Comp))
|
||||
{
|
||||
DoorComp->ToggleDoor();
|
||||
}
|
||||
(void)Comp; // 参数保留以匹配基类签名(OnInteractStarted 当前无调用方)
|
||||
|
||||
// v1.1 架构:门的开关业务逻辑由 EffectManager::ExecuteToggleDoor 统一驱动,
|
||||
// 视觉旋转由 UDoorInteractableComponent::ToggleDoor 内部回调 UpdateDoorVisual 完成。
|
||||
// 此处保留空实现,避免与 Effect 路径重复 ToggleDoor 导致状态抵消。
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -16,7 +16,7 @@ class UDoorInteractableComponent;
|
||||
*
|
||||
* 门类型的交互物 Actor。在基类基础上:
|
||||
* - 使用 UDoorInteractableComponent 替代 UInteractableComponent
|
||||
* - OnInteractStarted 中调用 ToggleDoor 并更新 Mesh 旋转
|
||||
* - v1.1:门开关业务由 EffectManager::ExecuteToggleDoor 驱动,OnInteractStarted 为空实现
|
||||
* - UpdateDoorVisual 执行实际的 Mesh Yaw 旋转(开门+90, 关门0)
|
||||
*
|
||||
* v0.1 阶段旋转为瞬时 SetRelativeRotation,不使用动画插值。
|
||||
@@ -39,9 +39,9 @@ public:
|
||||
// === 交互回调 ===
|
||||
|
||||
/**
|
||||
* 交互开始时调用。
|
||||
* Cast 到 UDoorInteractableComponent 后调用 ToggleDoor,
|
||||
* 由 Component 负责状态切换和持久化,Actor 只负责视觉。
|
||||
* 交互开始回调(v1.1 为空实现)。
|
||||
* 门开关业务逻辑由 EffectManager::ExecuteToggleDoor 统一驱动,
|
||||
* 视觉旋转由 UDoorInteractableComponent::ToggleDoor 内部回调,Actor 不在此重复处理。
|
||||
*/
|
||||
virtual void OnInteractStarted_Implementation(UInteractableComponent* Comp) override;
|
||||
|
||||
|
||||
@@ -149,6 +149,8 @@ void FEffectManager::ExecuteAction(const FInteractAction& Action)
|
||||
break;
|
||||
// v0.1 用日志占位的 Action
|
||||
case EInteractActionType::AddToBackpack:
|
||||
// TODO: 后续集成收集系统(Issue #33 P-013 收集系统程序实现)。
|
||||
// 届时由 ASystemDriver 回调链通知 FCollectionManager,EffectManager 不直接处理业务逻辑。
|
||||
UE_LOG(LogTemp, Log, TEXT("EffectManager: AddToBackpack - Item: %s"),
|
||||
CurrentContext.TargetComp.IsValid()
|
||||
? *CurrentContext.TargetComp->GetInteractableData().DisplayName
|
||||
@@ -328,7 +330,17 @@ void FEffectManager::ExecuteCameraReturn(const FInteractAction& Action)
|
||||
|
||||
PC->SetViewTargetWithBlend(CurrentContext.Instigator.Get(), Action.ReturnDuration);
|
||||
|
||||
// 延迟销毁 PushCamera(在 PerformCleanup 中统一清理)
|
||||
// 相机已回到角色,立即销毁推镜摄像机并清空缓存,
|
||||
// 避免 PerformCleanup 检测到有效缓存后冗余回位 + 重复销毁。
|
||||
if (APushCameraActor* PushCam = CachedPushCamera.Get())
|
||||
{
|
||||
CachedPushCamera = nullptr;
|
||||
if (PushCam->GetWorld())
|
||||
{
|
||||
PushCam->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Verbose, TEXT("EffectManager: CameraReturn (Dur=%.2fs)"), Action.ReturnDuration);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,20 +121,8 @@ UInteractableComponent* FInteractionManager::BeginInteract()
|
||||
State = EInteractionState::Executing;
|
||||
CurrentInteractable = Target;
|
||||
|
||||
// 通知 Character 进入交互状态(屏蔽移动)
|
||||
// FInteractionManager 只持有 ACharacter 基类指针,不直接依赖 AChildHoodCharacter。
|
||||
// 通过 UE 反射调用 SetInteracting(UFUNCTION(BlueprintCallable))。
|
||||
if (ACharacter* Char = PlayerCharacter.Get())
|
||||
{
|
||||
UFunction* Fn = Char->FindFunction(FName(TEXT("SetInteracting")));
|
||||
if (Fn)
|
||||
{
|
||||
struct FSetInteractingParams { bool bValue; };
|
||||
FSetInteractingParams Params;
|
||||
Params.bValue = true;
|
||||
Char->ProcessEvent(Fn, &Params);
|
||||
}
|
||||
}
|
||||
// SetInteracting(true) 由 Character 侧 OnInteract 直接调用(见 ChildHoodCharacter::OnInteract)。
|
||||
// FInteractionManager 作为纯逻辑层不操作 Character 表现状态,避免 SetInteracting(true) 双调用。
|
||||
|
||||
UE_LOG(LogChildHood, Log, TEXT("InteractionManager::BeginInteract: 开始交互 '%s'"),
|
||||
*Target->GetInteractableData().DisplayName);
|
||||
@@ -193,19 +181,8 @@ void FInteractionManager::OnInteractionFinished()
|
||||
// 清理当前交互物引用
|
||||
CurrentInteractable.Reset();
|
||||
|
||||
// 通知 Character 解除交互状态
|
||||
// 通过 UE 反射调用 SetInteracting(false)
|
||||
if (ACharacter* Char = PlayerCharacter.Get())
|
||||
{
|
||||
UFunction* Fn = Char->FindFunction(FName(TEXT("SetInteracting")));
|
||||
if (Fn)
|
||||
{
|
||||
struct FSetInteractingParams { bool bValue; };
|
||||
FSetInteractingParams Params;
|
||||
Params.bValue = false;
|
||||
Char->ProcessEvent(Fn, &Params);
|
||||
}
|
||||
}
|
||||
// SetInteracting(false) 由 ASystemDriver::OnEffectComplete 协调调用,
|
||||
// FInteractionManager 作为纯逻辑层不操作 Character 表现状态。
|
||||
|
||||
// 重新排序和刷新缓存(消耗可能改变了列表)
|
||||
UpdateSelection();
|
||||
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
/** 当前正在交互的交互物(Executing 状态下锁定) */
|
||||
TWeakObjectPtr<UInteractableComponent> CurrentInteractable;
|
||||
|
||||
/** 玩家角色弱引用(用于排序距离计算和 SetInteracting 调用) */
|
||||
/** 玩家角色弱引用(用于按水平距离排序的选中计算) */
|
||||
TWeakObjectPtr<ACharacter> PlayerCharacter;
|
||||
|
||||
/** Presentation 层缓存数据 — 选中交互物的摘要信息 */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "ChildHoodCharacter.h"
|
||||
|
||||
// ============================================================================
|
||||
// 构造函数
|
||||
@@ -108,4 +109,18 @@ void ASystemDriver::OnEffectComplete()
|
||||
{
|
||||
// Effect 完成后通知 InteractionManager 恢复 Free 状态
|
||||
InteractionManager.OnInteractionFinished();
|
||||
|
||||
// 通知 Character 复位交互状态(解除移动屏蔽)。
|
||||
// FInteractionManager 作为纯逻辑层不操作 Character 表现状态,
|
||||
// 由 ASystemDriver 作为 World 级协调者统一驱动。
|
||||
if (UWorld* World = GetWorld())
|
||||
{
|
||||
if (APlayerController* PC = World->GetFirstPlayerController())
|
||||
{
|
||||
if (AChildHoodCharacter* Char = Cast<AChildHoodCharacter>(PC->GetCharacter()))
|
||||
{
|
||||
Char->SetInteracting(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user