From 5df451011c35ca5a41bc0b9533f41a14cc2c9246 Mon Sep 17 00:00:00 2001 From: starmen1265 Date: Thu, 11 Jun 2026 11:25:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(interaction):=20Character=E5=92=8CPlayerCo?= =?UTF-8?q?ntroller=E9=9B=86=E6=88=90=E4=BA=A4=E4=BA=92=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/ChildHood/ChildHoodCharacter.cpp | 38 +++++++-- Source/ChildHood/ChildHoodCharacter.h | 25 +++++- .../ChildHood/ChildHoodPlayerController.cpp | 79 ++++++++++++++++++- Source/ChildHood/ChildHoodPlayerController.h | 28 ++++++- 4 files changed, 159 insertions(+), 11 deletions(-) diff --git a/Source/ChildHood/ChildHoodCharacter.cpp b/Source/ChildHood/ChildHoodCharacter.cpp index 60e34b8..afdb06b 100644 --- a/Source/ChildHood/ChildHoodCharacter.cpp +++ b/Source/ChildHood/ChildHoodCharacter.cpp @@ -11,12 +11,13 @@ #include "EnhancedInputSubsystems.h" #include "InputActionValue.h" #include "ChildHood.h" +#include "Interaction/InteractionManager.h" AChildHoodCharacter::AChildHoodCharacter() { // Set size for collision capsule GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); - + // Don't rotate when the controller rotates. Let that just affect the camera. bUseControllerRotationPitch = false; bUseControllerRotationYaw = false; @@ -46,15 +47,15 @@ AChildHoodCharacter::AChildHoodCharacter() FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); FollowCamera->bUsePawnControlRotation = false; - // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) - // are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++) + // 创建交互管理器组件 + InteractionManager = CreateDefaultSubobject(TEXT("InteractionManager")); } void AChildHoodCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { // Set up action bindings if (UEnhancedInputComponent* EnhancedInputComponent = Cast(PlayerInputComponent)) { - + // Jumping EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump); EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping); @@ -92,6 +93,12 @@ void AChildHoodCharacter::Look(const FInputActionValue& Value) void AChildHoodCharacter::DoMove(float Right, float Forward) { + // 交互中屏蔽移动 + if (bIsInteracting) + { + return; + } + if (GetController() != nullptr) { // find out which way is forward @@ -101,10 +108,10 @@ void AChildHoodCharacter::DoMove(float Right, float Forward) // get forward vector const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); - // get right vector + // get right vector const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); - // add movement + // add movement AddMovementInput(ForwardDirection, Forward); AddMovementInput(RightDirection, Right); } @@ -131,3 +138,22 @@ void AChildHoodCharacter::DoJumpEnd() // signal the character to stop jumping StopJumping(); } + +// ============================================================================ +// 交互系统方法 +// ============================================================================ + +UInteractionManager* AChildHoodCharacter::GetInteractionManager() const +{ + return InteractionManager; +} + +void AChildHoodCharacter::SetInteracting(bool bValue) +{ + bIsInteracting = bValue; +} + +bool AChildHoodCharacter::IsInteracting() const +{ + return bIsInteracting; +} diff --git a/Source/ChildHood/ChildHoodCharacter.h b/Source/ChildHood/ChildHoodCharacter.h index 33f7414..b4b9abf 100644 --- a/Source/ChildHood/ChildHoodCharacter.h +++ b/Source/ChildHood/ChildHoodCharacter.h @@ -10,6 +10,7 @@ class USpringArmComponent; class UCameraComponent; class UInputAction; +class UInteractionManager; struct FInputActionValue; DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All); @@ -30,7 +31,7 @@ class AChildHoodCharacter : public ACharacter /** Follow camera */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UCameraComponent* FollowCamera; - + protected: /** Jump Input Action */ @@ -49,10 +50,29 @@ protected: UPROPERTY(EditAnywhere, Category="Input") UInputAction* MouseLookAction; + /** 交互管理器组件 */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Interaction", meta = (AllowPrivateAccess = "true")) + UInteractionManager* InteractionManager; + + /** 是否处于交互状态(交互期间屏蔽移动) */ + bool bIsInteracting = false; + public: /** Constructor */ - AChildHoodCharacter(); + AChildHoodCharacter(); + + /** 获取交互管理器组件 */ + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Interaction") + UInteractionManager* GetInteractionManager() const; + + /** 设置交互状态(InteractionManager 调用,控制移动屏蔽) */ + UFUNCTION(BlueprintCallable, Category = "Interaction") + void SetInteracting(bool bValue); + + /** 查询当前是否在交互中 */ + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Interaction") + bool IsInteracting() const; protected: @@ -93,4 +113,3 @@ public: /** Returns FollowCamera subobject **/ FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; } }; - diff --git a/Source/ChildHood/ChildHoodPlayerController.cpp b/Source/ChildHood/ChildHoodPlayerController.cpp index cadaba8..febaaf6 100644 --- a/Source/ChildHood/ChildHoodPlayerController.cpp +++ b/Source/ChildHood/ChildHoodPlayerController.cpp @@ -1,7 +1,9 @@ // Copyright Epic Games, Inc. All Rights Reserved. - #include "ChildHoodPlayerController.h" +#include "ChildHoodCharacter.h" +#include "Interaction/InteractionManager.h" +#include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" #include "Engine/LocalPlayer.h" #include "InputMappingContext.h" @@ -57,6 +59,28 @@ void AChildHoodPlayerController::SetupInputComponent() } } } + + // 绑定交互输入(Enhanced Input Action) + if (UEnhancedInputComponent* EnhancedInputComponent = Cast(InputComponent)) + { + // 交互(E 键) + if (InteractAction) + { + EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &AChildHoodPlayerController::OnInteractPressed); + } + + // 取消(ESC 键) + if (CancelAction) + { + EnhancedInputComponent->BindAction(CancelAction, ETriggerEvent::Started, this, &AChildHoodPlayerController::OnCancelPressed); + } + + // 切换交互目标(Tab/滚轮) + if (SwitchInteractAction) + { + EnhancedInputComponent->BindAction(SwitchInteractAction, ETriggerEvent::Triggered, this, &AChildHoodPlayerController::OnSwitchInteract); + } + } } } @@ -65,3 +89,56 @@ bool AChildHoodPlayerController::ShouldUseTouchControls() const // are we on a mobile platform? Should we force touch? return SVirtualJoystick::ShouldDisplayTouchInterface() || bForceTouchControls; } + +// ============================================================================ +// 交互输入回调 +// ============================================================================ + +void AChildHoodPlayerController::OnInteractPressed() +{ + if (APawn* MyPawn = GetPawn()) + { + if (AChildHoodCharacter* Char = Cast(MyPawn)) + { + if (UInteractionManager* IM = Char->GetInteractionManager()) + { + // E 键双重功能:Free 状态发起交互,Active 阶段结束交互 + // BeginInteract 在非 Free 状态会被拒绝(内部 return) + // CancelInteract 在非 Interacting 状态或 AnimLock 阶段会被拒绝 + IM->BeginInteract(); + IM->CancelInteract(); + } + } + } +} + +void AChildHoodPlayerController::OnCancelPressed() +{ + if (APawn* MyPawn = GetPawn()) + { + if (AChildHoodCharacter* Char = Cast(MyPawn)) + { + if (UInteractionManager* IM = Char->GetInteractionManager()) + { + IM->CancelInteract(); + } + } + } +} + +void AChildHoodPlayerController::OnSwitchInteract(const FInputActionValue& Value) +{ + if (APawn* MyPawn = GetPawn()) + { + if (AChildHoodCharacter* Char = Cast(MyPawn)) + { + if (UInteractionManager* IM = Char->GetInteractionManager()) + { + // 读取 float 值作为方向:正值=下一个,负值=上一个 + float DirectionValue = Value.Get(); + int32 Direction = (DirectionValue >= 0.f) ? 1 : -1; + IM->SwitchTarget(Direction); + } + } + } +} diff --git a/Source/ChildHood/ChildHoodPlayerController.h b/Source/ChildHood/ChildHoodPlayerController.h index ddd4bf6..28a635d 100644 --- a/Source/ChildHood/ChildHoodPlayerController.h +++ b/Source/ChildHood/ChildHoodPlayerController.h @@ -7,7 +7,9 @@ #include "ChildHoodPlayerController.generated.h" class UInputMappingContext; +class UInputAction; class UUserWidget; +struct FInputActionValue; /** * Basic PlayerController class for a third person game @@ -17,7 +19,7 @@ UCLASS(abstract) class AChildHoodPlayerController : public APlayerController { GENERATED_BODY() - + protected: /** Input Mapping Contexts */ @@ -40,6 +42,20 @@ protected: UPROPERTY(EditAnywhere, Config, Category = "Input|Touch Controls") bool bForceTouchControls = false; + // === 交互输入 === + + /** 交互输入动作(E 键) */ + UPROPERTY(EditAnywhere, Category = "Input|Interaction") + UInputAction* InteractAction; + + /** 取消输入动作(ESC 键) */ + UPROPERTY(EditAnywhere, Category = "Input|Interaction") + UInputAction* CancelAction; + + /** 切换交互目标输入动作(Tab/滚轮) */ + UPROPERTY(EditAnywhere, Category = "Input|Interaction") + UInputAction* SwitchInteractAction; + /** Gameplay initialization */ virtual void BeginPlay() override; @@ -49,4 +65,14 @@ protected: /** Returns true if the player should use UMG touch controls */ bool ShouldUseTouchControls() const; +private: + + /** E 键按下回调:发起交互 */ + void OnInteractPressed(); + + /** ESC 键按下回调:取消/结束交互 */ + void OnCancelPressed(); + + /** Tab/滚轮回调:切换交互目标 */ + void OnSwitchInteract(const FInputActionValue& Value); };