0. 개요
메뉴 앵커(Menu Anchor)를 활용해 재확인 팝업을 설계한다.
(1) 슬롯 선택 이후 활성화된 슬롯 삭제 버튼을 클릭
(2) 재확인 팝업 위젯(Are You Sure?) 생성
- 제거 버튼을 클릭하면 슬롯을 제거
- 취소 버튼을 클릭하면 삭제를 취소하고 재확인 위젯을 제거
1. 재확인 팝업 위젯
(1) 위젯 디자인

(2) WBP_LoadScreen에서 메뉴 앵커로 재확인 위젯 띄우기
(2-1) 메뉴 앵커 디테일 패널

메뉴 앵커가 화면의 정중앙에 노출되게 할 것이다.
메뉴 앵커의 앵커를 화면 중앙으로 지정한다.
(2-2) 메뉴 앵커 내 위젯 배치 결정

띄울 위젯의 클래스를 지정하고 배치를 Center로 지정한다.
배치에 따라서 메뉴 앵커의 앵커 좌측, 우측, 가운데, 하단, 상단 등에 위젯을 생성한다.
(2-3) 이벤트 그래프에서 Toggle Open 함수 사용

메뉴 앵커의 위젯을 생성하려면 Toggle Open 함수를 호출한다.
Focus on Open 불리언을 True로 하면 메뉴 앵커 외부를 클릭할 시에 자동으로 팝업이 해제된다.

(2-4) 메뉴 앵커 내의 위젯 가져오기
생성된 위젯의 버튼을 이용하려면 메뉴 앵커 내의 위젯을 멤버 변수로 저장해야 한다.

사용자 메뉴 콘텐츠 구하기 이벤트에 바인드를 생성한다.
(메뉴 콘텐츠 구하기 이벤트는 Deprecated 되었음)

이 함수는 위젯을 생성하기 전에 해당 위젯에 대한 사전 설정을 가능하게 해준다.
AreYouSure 위젯을 외부에서 사용하기 위해 변수로 저장한다.
(2-5) WBP_AreYouSure에서 취소 버튼에 이벤트 디스패쳐 바인딩
새로운 이벤트 디스패쳐를 생성하고 Cancel 버튼 OnClicked 이벤트에 해당 디스패쳐를 호출한다.

(2-6) 메뉴 앵커 OnMenuOpenChanged 이벤트에 이벤트 디스패쳐 바인딩
메뉴 앵커가 열리면 OnMenuOpenChanged 이벤트가 호출된다.

여기에 이벤트 디스패쳐를 바인딩한다. 그리고 시작 버튼과 삭제 버튼을 활성화하고, 메뉴 앵커를 닫는다.
- 메뉴 앵커는 항상 WBP_LoadScreen 내에서 유효하므로, 바인딩도 항상 유효하다.
위젯이 닫힐 때에는 위젯이 제거되는데, 다시 팝업창을 열 때 위젯을 생성하며 멤버 변수로 저장하기 때문에 유효성에 문제가 없다.
순서는 아래와 같다.
(1) 메뉴 앵커에서 Toggle Open 호출
(2) 사용자 메뉴 콘텐츠 구하기 이벤트를 통해 WBP_AreYouSure를 생성하고 레퍼런스를 멤버 변수로 저장
(3) 메뉴 앵커가 WBP_AreYouSure를 뷰표트에 표시
(4) 생성이 되어 뷰포트에 출력되면 OnMenuOpenChanged 이벤트 호출, 이벤트 디스패쳐 바인딩
(5) 메뉴 앵커 Close 호출
2. 슬롯 삭제
(1) 확인 버튼 이벤트 디스패쳐

(2) 선택한 슬롯을 멤버 변수로 저장
// 재확인 창의 확인 버튼이 클릭됨
UFUNCTION(BlueprintCallable)
void ConfirmButtonPressed();
private:
UPROPERTY()
UMVVM_LoadSlot* SelectedSlot;
이제 선택한 슬롯의 포인터를 저장하고, 팝업 메뉴의 확인 버튼을 눌러 슬롯 데이터를 제거한다.
슬롯 선택 버튼을 누를 때 해당 슬롯의 포인터를 멤버 변수로 저장한다.
void UMVVM_LoadScreen::SelectSlotButtonPressed(int32 Slot)
{
// 게임 시작, 슬롯 삭제 델리게이트
SlotSelected.Broadcast();
// 슬롯에 접근해서 루프
for (const TPair<int32, UMVVM_LoadSlot*> LoadSlot : LoadSlots)
{
// 버튼 활성화 델리게이트 호출, 선택한 슬롯은 제외
if (LoadSlot.Key == Slot)
{
LoadSlot.Value->EnableSelectSlotButton.Broadcast(false);
}
else
{
LoadSlot.Value->EnableSelectSlotButton.Broadcast(true);
}
}
// 선택한 슬롯을 변수로 저장
SelectedSlot = LoadSlots[Slot];
}
(3) AuraGameModeBase에서 슬롯 제거 함수 선언
static void DeleteSlot(const FString& SlotName, int32 SlotIndex);
void AAuraGameModeBase::DeleteSlot(const FString& SlotName, int32 SlotIndex)
{
// 기존 슬롯의 저장 데이터를 제거
if (UGameplayStatics::DoesSaveGameExist(SlotName, SlotIndex))
{
UGameplayStatics::DeleteGameInSlot(SlotName, SlotIndex);
}
}
GameplayStatics의 함수인 DeleteGameInSlot 함수를 사용하는 슬롯 제거 함수를 선언한다.
(4) MVVM_LoadScreen의 확인 버튼 콜백 함수
void UMVVM_LoadScreen::ConfirmButtonPressed()
{
if (IsValid(SelectedSlot))
{
AAuraGameModeBase::DeleteSlot(SelectedSlot->LoadSlotName, SelectedSlot->SlotIndex);
}
// 위젯 슬롯 체인져
}
MVVM_LoadSlot의 SlotIndex가 FString으로 되어 있으므로 int32로 타입을 변경한다.
(4-1) 슬롯 초기화 시에 슬롯 인덱스 부여
void UMVVM_LoadScreen::InitializeLoadSlots()
{
LoadSlot_0 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);
LoadSlot_0->LoadSlotName = FString("LoadSlot_0");
LoadSlot_0->SlotIndex = 0;
LoadSlot_1 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);
LoadSlot_1->LoadSlotName = FString("LoadSlot_1");
LoadSlot_1->SlotIndex = 1;
LoadSlot_2 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);
LoadSlot_2->LoadSlotName = FString("LoadSlot_2");
LoadSlot_2->SlotIndex = 2;
LoadSlots.Add(0, LoadSlot_0);
LoadSlots.Add(1, LoadSlot_1);
LoadSlots.Add(2, LoadSlot_2);
}
(4-2) 데이터 제거 후 슬롯 위젯 초기화
void UMVVM_LoadScreen::ConfirmButtonPressed()
{
if (IsValid(SelectedSlot))
{
AAuraGameModeBase::DeleteSlot(SelectedSlot->LoadSlotName, SelectedSlot->SlotIndex);
// 슬롯 상태 초기화
SelectedSlot->SlotStatus = Vacant;
SelectedSlot->InitializeSlot();
}
}
MVVM_LoadSlot은 InitializeSlot 함수 내에서 SlotStatus에 따라 블루프린트로 델리게이트를 호출하기 때문에, 적절히 UI가 초기화될 것이다.
(5) WBP_LoadScreen에서 확인 버튼에 이벤트 바인딩

확인 버튼 콜백 함수를 호출하고, 메뉴 앵커의 Close를 호출한다.
3. 디버그
(1) 슬롯 삭제 후 재선택하여 슬롯을 생성하면 Editable Text 내용이 남아있는 버그
WBP_LoadSlot_EnterName에서 슬롯 생성 버튼을 누른 후 편집가능한 텍스트의 텍스트를 빈 칸으로 지정한다.

(2) 슬롯 삭제 후 버튼이 비활성화 되어 있는 버그
삭제 확인 버튼을 누르면 슬롯 선택 버튼을 활성화한다.
void UMVVM_LoadScreen::ConfirmButtonPressed()
{
if (IsValid(SelectedSlot))
{
AAuraGameModeBase::DeleteSlot(SelectedSlot->LoadSlotName, SelectedSlot->SlotIndex);
// 슬롯 상태 초기화
SelectedSlot->SlotStatus = Vacant;
SelectedSlot->InitializeSlot();
SelectedSlot->EnableSelectSlotButton.Broadcast(true);
}
}
'UE 5 스터디 > Gameplay Ability System(GAS)' 카테고리의 다른 글
28-14. 로드 메뉴 UI - (10) 맵 불러오기 (0) | 2025.04.07 |
---|---|
28-13. 로드 메뉴 UI - (9) 필드 노티파이 - 맵 이름 가져오기 (0) | 2025.04.07 |
28-11. 로드 메뉴 UI - (7) MVVM - 슬롯 선택 버튼 (0) | 2025.04.04 |
28-10. 저장 - (2) 저장 상태 (0) | 2025.04.02 |
28-9. 로드 메뉴 UI - (6) MVVM 필드 노티파이 - 뷰에 뷰 모델의 멤버 변수 바인딩 (0) | 2025.04.02 |