작성
·
679
0
<#include "Item/ABItemBat.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "Physics/WMACollsion.h"
#include "Interface/ABCharacterItemInterface.h"
#include "Character/WMACharacterPlayer.h"
#include <GameData/WMAGameInstance.h>
#include "Blueprint/UserWidget.h"
#include "Components/WidgetComponent.h"
#include "UI/WMAItemInteractionWidget.h"
#include "Interface/ABCharacterItemInterface.h"
// Sets default values
AABItemBat::AABItemBat()
{
Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
Effect = CreateDefaultSubobject < UParticleSystemComponent>(TEXT("Effect"));
TextE = CreateDefaultSubobject<UWidgetComponent>(TEXT("TextE"));
Item = CreateDefaultSubobject<UABItemData>(TEXT("ItemBat"));
static ConstructorHelpers::FClassFinder<UUserWidget>InputE(TEXT("WidgetBlueprint'/Game/UI/WBP_ItemInteraction.WBP_ItemInteraction_C'"));
if (InputE.Succeeded()) {
InteractionItemWidgetClass = InputE.Class;
}
RootComponent = Trigger;
Mesh->SetupAttachment(Trigger);
Effect->SetupAttachment(Trigger);
Trigger->SetCollisionProfileName(CPROFILE_WMATRIGGER);
Trigger->SetBoxExtent(FVector(11.0f, 10.0f, 110.0f));
Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBat::OnOverlapBegin);
Trigger->OnComponentEndOverlap.AddDynamic(this,&AABItemBat::OnOverlapEnd);
static ConstructorHelpers::FObjectFinder<UStaticMesh> BoxMeshRef(TEXT("/Script/Engine.StaticMesh'/Game/Item/Bat/Batfbx.Batfbx'"));
if (BoxMeshRef.Succeeded()) {
TempBoxMesh = BoxMeshRef.Object;
Mesh->SetStaticMesh(BoxMeshRef.Object);
}
Mesh->SetRelativeLocation(FVector(0.0f, -3.5f, -20.0f));
Mesh->SetCollisionProfileName(TEXT("NoCollision"));
bInteractionItem = false;
PrimaryActorTick.bCanEverTick = true;
}
void AABItemBat::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//UE_LOG(LogTemp, Warning, TEXT("Character is Die :: %s"), bInteractionItem ? TEXT("true") : TEXT("false"));
if (bInteractionItem) {
Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBat::OnOverlapBegin);
UE_LOG(LogTemp,Warning,TEXT("NO item Attach"))
}
}
void AABItemBat::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
//TextE->SetHiddenInGame(false);
if (InteractionItemWidgetClass) {
ItemText = CreateWidget<UUserWidget>(GetWorld(), InteractionItemWidgetClass);
if(ItemText)
ItemText->AddToViewport();
}
if (nullptr == Item) {
Destroy();
return;
}
//UE_LOG(LogTemp, Warning, TEXT("Character is Die :: %s"), bInteractionItem ? TEXT("true") : TEXT("false"));
if (bInteractionItem) {
IABCharacterItemInterface* OverlappingPawn = Cast<IABCharacterItemInterface>(OtherActor);
if (OverlappingPawn) {
OverlappingPawn->TakeItem(Item);
//TextE->SetHiddenInGame(true);
}
//Effect->Activate(true);
Mesh->SetHiddenInGame(true);
SetActorEnableCollision(false);
Effect->OnSystemFinished.AddDynamic(this, &AABItemBat::OnEffectFinished);
Trigger->OnComponentBeginOverlap.RemoveDynamic(this, &AABItemBat::OnOverlapBegin);
}
}
void AABItemBat::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (ItemText) {
ItemText->RemoveFromViewport();
ItemText = nullptr;
}
}
void AABItemBat::OnEffectFinished(UParticleSystemComponent* ParticleSystem)
{
Destroy();
}
void AABItemBat::StartInteractionItem()
{
bInteractionItem = true;
}
void AABItemBat::StopInteractionItem()
{
//bInteractionItem = false;
}>
일단 WMACharacterplayer.cpp에서 StartInteractionItem()을 호출하는데는 문제가 없습니다.
StartInteractionItem() 함수 내부에서 로그를 출력해보면 bInteractionItem이 true로 잘 출력이 되는 것을 확인할 수 있습니다.
문제는 Tick함수 내부와 OnOverlapBegin()함수 내부에서 로그를 찍어보면 bInteractionItem이 false로 변경되어서 OnOverlapBegin()함수를 호출하지 못하고 있는 상황입니다.
혹시 어느 부분이 문제가 되어 bool값이 변경되는지 여쭐수 있을까요?
답변 1
0
음.. 코드를 보면 제가 만든 예제 코드는 아닌것 같은데,
우선 Tick에서 델리게이트를 등록하는 코드는 안 좋은 방법입니다.
Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBat::OnOverlapBegin);
원하시는 기능이 어떤 것인지 정확히 모르겠지만, 다른 형태로 해결 방법을 고민하셔야 할 것 같아요.
기본적인 액터의 구성 요소의 초기화는 델리게이트 지정은 생성자나 PostInitializeComponents 함수에서 해주시고, OnOverlapBegin 같은 이벤트 함수에서는 상태 값만 변경하도록 지정해주시는게 좋습니다.
AddDynamic을 두 번 이상 호출한다면 Remove를 명확하게 맞춰 델리게이트가 객체에 하나만 연동되게끔 잘 정리해주시고요, Tick함수는 사용자 입력 처리와 같이 매 프레임마다 점검하는 용도가 아니라면 가급적 사용하지 않는게 좋습니다.
하나의 함수에서 if 문으로 여러 분기를 만들어 직접 처리하기보다 상태 값을 변경하고, 상태의 변경을 감지해 자연스럽게 처리하는 함수를 호출하도록 구조를 한번 고민해보세요.
한 번 다시 정리해보시면서 디버깅을 활용하면 원하시는 답을 찾을 수 있지 않을까 생각합니다.