[CH4-19] 게임오버 랭킹 UI

김여울·2025년 10월 6일

내일배움캠프

목록 보기
91/139

⚠️ 문제

  • 게임오버 화면에서 랭킹 표시 시 ScrollBox + 동적 TextBlock 생성 방식 사용
  • 주요 문제:
    1. 한글 폰트 깨짐 → "1위 : 닉네임" 표시 시 한글이 제대로 나오지 않음
    2. 코드 복잡성 → 동적 위젯 생성, 폰트/스타일 수동 지정으로 유지보수 어려움
    3. 바인딩 에러 → 위젯 이름 불일치, include 순서 오류, 중복 구조체 정의 문제로 컴파일 에러 빈번

🔍 원인

  • 잘못된 위젯 타입 선택 (Editable Text, TextBox 구분 오류)
  • ScrollBox + TextBlock 동적 생성 → 스타일 적용이 코드에 강하게 결합
  • DCResultTypes 구조체가 중복 정의되어 참조 에러 발생
  • include 순서 및 슬롯 캐스팅 누락으로 C2027, undefined 등 빌드 에러 다수 발생

🚧 조치

1. UI 위젯 구조 변경

  • ScrollBox + TextBlock 다수 → VerticalBox 고정 6칸 레이아웃으로 전환
  • 각 Row = HorizontalBox (Image 메달 + TextBlock 랭킹 텍스트)
  • 필요 시 MultiLineEditableTextBox 구조도 고려 가능했으나, 디자인상 고정된 6칸이 더 적합

2. 데이터 구조 통일

  • Source/DC/Game/DCResultTypes.h 하나로 통합
  • FPlayerResult { Nickname, Rank }, FPlayerKillResult { Nickname, Kills }
  • 다른 헤더에 있던 중복 USTRUCT 제거, include만 사용

3. include / 빌드 에러 해결

  • GameState.h에서 #include "Game/DCResultTypes.h"를 generated.h 이전에 배치
  • DCGameOverWidget.cpp 상단에 #include "Components/HorizontalBoxSlot.h" 추가

4. PopulateRankingRows() 구현

void UDCGameOverWidget::PopulateRankingRows()
{
    // GameState/Instance에서 데이터 수집 후 정렬
    // Rank↑, Kills↓, Name↑
    for (int32 i = 0; i < 6 && i < Results.Num(); ++i)
    {
        AddRankingRow(i+1, Results[i].Nickname, Results[i].Kills);
    }
}

void UDCGameOverWidget::AddRankingRow(int32 ViewRank, const FString& Nick, int32 Kills)
{
    if (UHorizontalBox* Row = Cast<UHorizontalBox>(RankingList->GetChildAt(ViewRank-1)))
    {
        // 메달 이미지
        if (UImage* Medal = Cast<UImage>(Row->GetChildAt(0)))
        {
            FSlateBrush Brush;
            Brush.SetResourceObject(MedalTextures[ViewRank]);
            Brush.ImageSize = FVector2D(40, 40);
            Medal->SetBrush(Brush);
        }

        // 랭킹 텍스트
        if (UTextBlock* Label = Cast<UTextBlock>(Row->GetChildAt(1)))
        {
            auto Font = Label->GetFont();
            Font.Size = 30;
            Label->SetFont(Font);

            Label->SetText(FText::FromString(
                FString::Printf(TEXT("%d위 : %s (%d Kill%s)"),
                    ViewRank, *Nick, Kills, Kills==1?TEXT(""):TEXT("s"))));
        }
    }
}

💡 결과

  • UI는 고정된 VerticalBox(6칸)로 단순화 → 코드 70% 이상 감소
  • 메달 이미지 40×40, 폰트 사이즈 30, Row Padding (8,4,8,4) 로 UI 안정화
  • 반응형 레이아웃은 스트레치 앵커, 고정형은 한 점 앵커로 대응 가능
  • 유지보수 및 스타일 수정은 블루프린트에서 직관적으로 가능

0개의 댓글