📍 4주차 2강

Size X / Y 로 크기 맞추기 
Position X / Y - 1920 * 1080 의 반값Alignment - 0.5로 하면 중앙에 정렬Size X / Y 조절
메뉴 UI를 띄울 때는 메뉴 전용 Map을 만드는게 좋음
📍 File > NewLevel
📍 File > Save Current Level AS > MenuLevel
MenuLevel을 Default Map으로 설정
PlayerController가 UI 담당
// PlayerController.h
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "HUD") // ✅ 수정
UUserWidget* HUDWidgetInstance;
// 메뉴 UI
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Menu")
TSubclassOf<UUserWidget> MainMenuWidgetClass;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Menu")
UUserWidget* MainMenuWidgetInstance;
// ...
// HUD창 가져오는 함수
UFUNCTION(BlueprintCallable, Category = "HUD")
void ShowGameHUD();
// 메인 메뉴창 가져오는 함수
UFUNCTION(BlueprintCallable, Category = "Menu")
void ShowMainMenu(bool bIsRestart); // 처음: Start, GameOver: Restart - bool 변수
// MainMenu의 StartButton - 게임 시작 함수
// Start & Restart - 거의 똑같음 -> StartGame으로 묶기
UFUNCTION(BlueprintCallable, Category = "Menu")
void StartGame();
// PlayerController.cpp
#include "Kismet/GameplayStatics.h"
#include "Components/TextBlock.h" // MainMenu Text 관련
ASpartaPlayerController::ASpartaPlayerController() // 생성자 정의
: //...
MainMenuWidgetClass(nullptr),
MainMenuWidgetInstance(nullptr)
{
}
// ...
// 메뉴 UI 표시
void ASpartaPlayerController::ShowMainMenu(bool bIsRestart)
{
// HUD가 켜져 있다면 닫기
if (HUDWidgetInstance)
{
HUDWidgetInstance->RemoveFromParent(); // 뷰포트에서 떼어내고
HUDWidgetInstance = nullptr; // nullptr로 처리
}
// 이미 메뉴가 떠 있으면 제거
if (MainMenuWidgetInstance)
{
MainMenuWidgetInstance->RemoveFromParent();
MainMenuWidgetInstance = nullptr;
}
// 메뉴 UI 생성
if (MainMenuWidgetClass)
{
MainMenuWidgetInstance = CreateWidget<UUserWidget>(this, MainMenuWidgetClass);
if (MainMenuWidgetInstance)
{
MainMenuWidgetInstance->AddToViewport(); // 메인메뉴 생기면 뷰포트에 연결
// 뒤에 게임(레벨)이 떠있으면 마우스 움직일 때 캐릭터 시점 조작될 수 있음
// 막기 위해서 마우스 포커스가 UI로만 가게
bShowMouseCursor = true; // 게임에선 마우스 커서 안 보이지만 UI에선 보이게
SetInputMode(FInputModeUIOnly()); // UI만 사용 가능하게 InputMode 처리
}
// 메인메뉴가 Start? Restart?
if (UTextBlock* ButtonText = Cast<UTextBlock>(MainMenuWidgetInstance->GetWidgetFromName(TEXT("StartButtonText"))))
{
if (bIsRestart)
{
ButtonText->SetText(FText::FromString(TEXT("Restart")));
}
else
{
ButtonText->SetText(FText::FromString(TEXT("Start")));
}
}
}
}
// 게임 HUD 표시
void ASpartaPlayerController::ShowGameHUD()
{
// HUD가 켜져 있다면 닫기
if (HUDWidgetInstance)
{
HUDWidgetInstance->RemoveFromParent();
HUDWidgetInstance = nullptr;
}
// 이미 메뉴가 떠 있으면 제거
if (MainMenuWidgetInstance)
{
MainMenuWidgetInstance->RemoveFromParent();
MainMenuWidgetInstance = nullptr;
}
if (HUDWidgetClass)
{
HUDWidgetInstance = CreateWidget<UUserWidget>(this, HUDWidgetClass);
if (HUDWidgetInstance)
{
HUDWidgetInstance->AddToViewport();
bShowMouseCursor = false; // 게임중이니까 마우스 커서는 없애기
SetInputMode(FInputModeGameOnly()); // 인풋모드는 게임에서만 사용해!
ASpartaGameState* SpartaGameState = GetWorld() ? GetWorld()->GetGameState<ASpartaGameState>() : nullptr;
if (SpartaGameState)
{
SpartaGameState->UpdateHUD(); // 업데이트해서 갱신
}
}
}
}
// 게임 시작 - BasicLevel 오픈, GameInstance 데이터 리셋
void ASpartaPlayerController::StartGame()
{
// GameInstance에 있는 정보들 초기화
if (USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(UGameplayStatics::GetGameInstance(this)))
{
SpartaGameInstance->CurrentLevelIndex = 0;
SpartaGameInstance->TotalScore = 0;
}
// 지금은 UI 전용 Level에 있음
// BasicLevel 오픈해라~
UGameplayStatics::OpenLevel(GetWorld(), FName("BasicLevel"));
}
// GameState.cpp
void ASpartaGameState::StartLevel()
{
// 레벨 오픈 -> 메뉴UI (x) / HUD UI (o)
if (APlayerController* PlayerController = GetWorld()->GetFirstPlayerController())
{
if (ASpartaPlayerController* SpartaPlayerController = Cast<ASpartaPlayerController>(PlayerController))
{
SpartaPlayerController->ShowGameHUD();
}
}
}
void ASpartaGameState::OnGameOver()
{
if (APlayerController* PlayerController = GetWorld()->GetFirstPlayerController())
{
if (ASpartaPlayerController* SpartaPlayerController = Cast<ASpartaPlayerController>(PlayerController))
{
SpartaPlayerController->ShowMainMenu(true); // Restart bool : true
}
}
}


☑ Is Variable → 이벤트 활성화

// PlayerController.cpp
void ASpartaPlayerController::BeginPlay()
{
// ...
// 현재 맵이 mainmap일 경우만 mainmenu 띄우기
FString CurrentMapName = GetWorld()->GetMapName();
if (CurrentMapName.Contains("MenuLevel"))
{
ShowMainMenu(false);
}
/*
if (HUDWidgetClass)
{
// HUDWidgetClassf라는 instance 만들어서 HUDWidget에 할당해라!
HUDWidgetInstance = CreateWidget<UUserWidget>(this, HUDWidgetClass);
if (HUDWidgetInstance) // 안전코드
{
HUDWidgetInstance->AddToViewport(); // 생성된 위젯을 뷰포트에 추가해줘
}
}
// 위젯을 뷰포트에 부른 직후 초기화
ASpartaGameState* SpartaGameState = GetWorld() ? GetWorld()->GetGameState<ASpartaGameState>() : nullptr;
if (SpartaGameState)
{
SpartaGameState->UpdateHUD();
}
*/
}
// GameState.cpp
void ASpartaGameState::BeginPlay()
{
Super::BeginPlay();
// UpdateHUD(); ✅ 지우기
StartLevel();
GetWorldTimerManager().SetTimer(
HUDUpdateTimerHandle,
this, // 이 객체에서
&ASpartaGameState::UpdateHUD, // 시간이 끝나면 이 함수 불러~
0.1f, // 0.1 초마다 UpdateHUD 불러
true // 반복
);
}


| 구분 | 일반 함수 | static 함수 |
|---|---|---|
| 호출 방식 | 객체 생성 후 객체->함수() | 객체 없이 클래스::함수() |
| this 사용 | 가능 | 불가능 |
| 멤버 변수 접근 | 가능 | 불가능 |
| 주 용도 | 객체의 상태를 다룰 때 | 공용 기능, 유틸리티 함수 등 |
// 일반 함수
class UMyActor : public AActor
{
public:
void SayHello()
{
UE_LOG(LogTemp, Warning, TEXT("Hello from object!"));
}
};
// 일반 함수 - 사용
UMyActor* Actor = GetWorld()->SpawnActor<UMyActor>();
Actor->SayHello(); // ✅ 객체를 만들어야 호출 가능
// static 함수
class UMyHelper
{
public:
static void SayHello()
{
UE_LOG(LogTemp, Warning, TEXT("Hello from static!"));
}
};
// static 함수 - 사용
// 사용법
UMyHelper::PrintMessage(); // ✅ 클래스 이름으로 바로 호출!