⚠️ 문제

- 게임오버 화면에서 랭킹 표시 시 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()
{
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 안정화
- 반응형 레이아웃은 스트레치 앵커, 고정형은 한 점 앵커로 대응 가능
- 유지보수 및 스타일 수정은 블루프린트에서 직관적으로 가능