ADoor가 ADarkLetter를 직접 참조해서 그 편지가 읽혔는지 물어보고 그 결과에 따라 나눈다

 

1. DarkLetter에 읽음 상태 추가

.h

UPROPERTY(BlueprintReadOnly, Category = "Letter")
bool bRead = false;

public:
    bool IsRead() const;

 

 

.cpp

 

bool ADarkLetter::IsRead() const
{
    return bRead;
}

 

ActivateItem에서 편지를 처음 펼치는 순간에 아래 코드를 추가한다.

else if (LetterWidgetClass)
{
    ...
    bRead = true;   // 한번 열리면 영구히 true (닫아도 false로 안 돌아감)
}

 

 

 

2. Door.h : 편지 참조와 잠김 메시지 변수 추가

class ADarkLetter;          // 전방 선언
class UInteractionWidget;   // 전방 선언

protected:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Door")
    ADarkLetter* RequiredLetter;              

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Door")
    TSubclassOf<UInteractionWidget> LockedMessageClass;  

    UPROPERTY()
    UInteractionWidget* LockedWidgetInstance;

 

 

3. Door.cpp : ActivateItem

void ADoor::ActivateItem(AActor* Activator)
{
    if (Activator && Activator->ActorHasTag("Player"))
    {
        ATheRoomCharacter* PlayerCharacter = Cast<ATheRoomCharacter>(Activator);
        if (!PlayerCharacter) return;

        if (RequiredLetter && !RequiredLetter->IsRead())
        {
            // 편지와 동일 패턴
            if (LockedWidgetInstance)
            {
                LockedWidgetInstance->RemoveFromParent();
                LockedWidgetInstance = nullptr;
                PlayerCharacter->ShowInteraction();
            }
            else if (LockedMessageClass)
            {
                LockedWidgetInstance = CreateWidget<UInteractionWidget>(GetWorld(), LockedMessageClass);
                LockedWidgetInstance->AddToViewport();
                PlayerCharacter->HideInteraction();
            }
        }
        else
        {
            // 읽었으면 (또는 편지 연결 안 됐으면) → 레벨 전환
            UGameplayStatics::OpenLevel(this, FName("BrightRoom"));
        }
    }
}

 

 

4. 에디터

WBP_Interaction를 Duplicate해서 WBP_DoorLocked를 만들고 텍스트만 "문이 잠겨있다"로 바꿈

그리고 레벨(DarkRoom)에 배치된 Door 액터를 선택해서 Details 패널에서 RequiredLetter에 레벨에 배치된 BP_DarkLetter 인스턴스를 LockedMessageClass에 WBP_DoorLocked를 연결했다

 

새롭게 알게된 것

클래스 vs 인스턴스

RequiredLetter 같은 참조는 블루프린트 클래스 디폴트, 즉 설계도 자체에서는 설정할 수 없다는 걸 배웠다
설정은 레벨에 실제로 배치된 그 인스턴스에서만 가능하다

 

이유를 알아보니 설계도는 "이 클래스에 속하는 모든 객체가 보편적으로 어때야 하는가"를 정의하는 자리다.

RequiredLetter는 "이 문이 기다리는 편지는 바로 저 편지다"라는 특정 레벨에만 존재하는 구체적인 사실이기 때문에 설계도 수준에서는 의미를 가질 수 없다

(같은 Door 클래스를 다른 레벨에 또 배치한다면 그 문은 또 다른 편지를 기다릴 수도 있어야 하니까)

 

LockedMessageClass처럼 TSubclassOf로 잡은 변수는 "어떤 종류의 위젯을 쓸지"라는 보편적인 설계 정보라서 클래스 디폴트에서도 지정할 수 있지만, ADarkLetter* 같은 특정 액터 참조는 레벨 위에 놓인 그 인스턴스를 가리켜야 하므로 레벨 인스턴스에서만 채울 수 있다.

+ Recent posts