상호작용 UI - 1

김여울·2025년 12월 26일

내일배움캠프

목록 보기
136/139

목표

  • 상호작용 가능 액터 표시를 위한 하이라이트 효과
  • 알맞은 상호작용 키를 액터 옆에 배치

적용해야할 상호작용 UI

Interactable Actor - Left Click
ㄴ CustomizeStation
ㄴ ChapterSelectActor

Pickable Actor - E Key
ㄴ BaseToy 상속 받은 장난감들

Movable Actor - WASD (Arrow)
ㄴ MovableActor

상호작용 인터페이스 만들기 (Interactable)

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 상속) 생성

코드 만들기

InteractionPromptWidget.h

#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;
};

InteractionPromptWidget.cpp

#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();
}

오늘은 위젯 만들고 인터페이스까지만 적용!

0개의 댓글