Interactable Actor - Left Click
ㄴ CustomizeStation
ㄴ ChapterSelectActor
Pickable Actor - E Key
ㄴ BaseToy 상속 받은 장난감들
Movable Actor - WASD (Arrow)
ㄴ MovableActor
UENUM(BlueprintType)
enum class EInteractionType : uint8
{
None,
LeftClick, // 챕터 고르기, 커스터마이징
PickupKey, // E키 - PickableActor
MoveKey // W키 - MovableActor
};
class ALNCharacter;
UINTERFACE(MinimalAPI)
class ULNIInteractable : public UInterface
{
GENERATED_BODY()
};
class OURLONGNIGHT_API ILNIInteractable
{
GENERATED_BODY()
public:
// 상호작용 UI
virtual void LeftClickInteract(AActor* Interactor) {}
virtual void RightClickInteract(AActor* Interactor) {}
virtual void PickupKeyInteract(AActor* Interactor) {}
virtual void MoveKeyInteract(AActor* Interactor) {}
// 상호작용 가능 액터 표시를 위한 하이라이트 효과
virtual void BeginHighlight() {}
virtual void EndHighlight() {}
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "LN|Interaction")
EInteractionType GetInteractionType() const;
virtual EInteractionType GetInteractionType_Implementation() const { return EInteractionType::None; }
};
UserWidget으로 생성
1. WBP_LeftClickPrompt (UserWidget)
2. WBP_PickupKeyPrompt (UserWidget)
3. WBP_MoveKeyPrompt (UserWidget)


액터마다 맞는 상호작용 UI를 띄우기 위해 WBP_InteractionPrompt (InteraactionPromptWidget 상속) 생성

#pragma once
#include "CoreMinimal.h"
#include "CommonActivatableWidget.h"
#include "Interface/LNIInteractable.h"
#include "InteractionPromptWidget.generated.h"
UCLASS()
class OURLONGNIGHT_API UInteractionPromptWidget : public UCommonActivatableWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
UPROPERTY(meta = (BindWidget))
class UUserWidget* LeftClickPrompt;
UPROPERTY(meta = (BindWidget))
class UUserWidget* PickupKeyPrompt;
UPROPERTY(meta = (BindWidget))
class UUserWidget* MoveKeyPrompt;
UFUNCTION()
void OnInteractionChanged(EInteractionType InteractionType);
void HideAllPrompts();
private:
UPROPERTY()
class ALNCharacter* CachedCharacter;
};
#include "UI/Widget/InteractionPromptWidget.h"
#include "Character/LNCharacter.h"
#include "Components/Widget.h"
#include "Player/Controller/LNControllerInGame.h"
void UInteractionPromptWidget::NativeConstruct()
{
Super::NativeConstruct();
if (APlayerController* PC = GetOwningPlayer())
{
if (ALNCharacter* Character = Cast<ALNCharacter>(PC->GetPawn()))
{
CachedCharacter = Character;
Character->OnInteractionAvailable.AddDynamic(this, &UInteractionPromptWidget::OnInteractionChanged);
}
}
HideAllPrompts();
}
void UInteractionPromptWidget::OnInteractionChanged(EInteractionType InteractionType)
{
HideAllPrompts();
switch (InteractionType)
{
case EInteractionType::LeftClick:
if (LeftClickPrompt)
{
LeftClickPrompt->SetVisibility(ESlateVisibility::HitTestInvisible);
}
break;
case EInteractionType::PickupKey:
if (PickupKeyPrompt)
{
PickupKeyPrompt->SetVisibility(ESlateVisibility::HitTestInvisible);
}
break;
case EInteractionType::MoveKey:
if (MoveKeyPrompt)
{
MoveKeyPrompt->SetVisibility(ESlateVisibility::HitTestInvisible);
}
break;
case EInteractionType::None:
default:
break;
}
}
void UInteractionPromptWidget::HideAllPrompts()
{
if (LeftClickPrompt)
{
LeftClickPrompt->SetVisibility(ESlateVisibility::Collapsed);
}
if (PickupKeyPrompt)
{
PickupKeyPrompt->SetVisibility(ESlateVisibility::Collapsed);
}
if (MoveKeyPrompt)
{
MoveKeyPrompt->SetVisibility(ESlateVisibility::Collapsed);
}
}
void UInteractionPromptWidget::NativeDestruct()
{
if (CachedCharacter)
{
CachedCharacter->OnInteractionAvailable.RemoveDynamic(this, &UInteractionPromptWidget::OnInteractionChanged);
CachedCharacter = nullptr;
}
Super::NativeDestruct();
}
오늘은 위젯 만들고 인터페이스까지만 적용!