[25.05.27] :: 가디언 앤 시커 프로젝트 08

chooha·2025년 5월 27일

가디언앤시커

목록 보기
8/25

📝 개발일지 - 룬 시스템 스탯 초기화 버그 트러블슈팅

👨‍💻 오늘의 개발 작업

오늘은 룬 시스템의 스탯창에서 총합 계산이 잘못되는 버그를 해결했음
처음엔 수학 계산 오류인 줄 알았는데 알고 보니 언리얼 위젯의 생명주기를 제대로 이해하지 못해서 생긴 문제였음


💡 오늘의 5분 기록

1. 문제 확인 - 스탯 총합이 이상하게 계산됨

스탯 패널 UI를 구현하고 테스트하니까 뭔가 이상했음

그리드를 처음 로드했을 때 이미 배치된 룬이 있는 경우 해당 스탯은 총합이 제대로 된 결과가 나오지 않았고, 룬을 배치했을 때 기존 베이스 스탯이 빠진 룬 효과만 반영되는 문제가 발생
위젯을 생성하고 InitStat()을 해줄 때 분명히 100으로 설정되는데 왜 0이 나오는지 이해할 수 없었음

2. 원인 파악 - 위젝 생명주기 오해

로그를 찍어보니 값이 설정되는 순서가 예상과 달랐음

문제가 된 호출 순서:

1. CreateWidget() → 위젯 생성
2. InitStat(BaseValue = 100) → 올바른 값 설정
3. AddChild() → 위젯을 화면에 추가
4. NativeConstruct(BaseValue = 0) → 값이 리셋됨!
5. UpdateUI() → 잘못된 계산 (0 + 20 = 20)
// 문제가 된 코드
void UGS_StatDataWidget::InitStat(FName InStatName, float InBaseValue)
{
    StatName = InStatName;
    BaseValue = InBaseValue;  // 여기서는 100 설정
    UE_LOG(LogTemp, Warning, TEXT("InitStat: %s = %.1f"), *StatName.ToString(), BaseValue);
}

void UGS_StatDataWidget::NativeConstruct()
{
    Super::NativeConstruct();
    BaseValue = 0.0f;        // 여기서 0으로 리셋됨!
    CurrRuneValue = 0.0f;
    CurrBonusValue = 0.0f;
}

핵심 깨달음:

  • NativeConstruct()는 위젯이 화면에 나타날 때 호출됨 (AddChild 이후)
  • InitStat()은 개발자가 직접 호출하는 함수 (AddChild 이전)
  • 따라서 InitStat()에서 설정한 값이 NativeConstruct()에서 덮어써짐

3. 해결 과정 - 로그를 통한 추적

단계별로 어디서 값이 변하는지 추적해봤음

void UGS_StatDataWidget::InitStat(FName InStatName, float InBaseValue)
{
    StatName = InStatName;
    BaseValue = InBaseValue;
    UE_LOG(LogTemp, Warning, TEXT("InitStat: %s = %.1f"), *StatName.ToString(), BaseValue);
}

void UGS_StatDataWidget::NativeConstruct()
{
    UE_LOG(LogTemp, Warning, TEXT("NativeConstruct 호출 - BaseValue: %.1f"), BaseValue);
    BaseValue = 0.0f;  // 문제 지점!
    UE_LOG(LogTemp, Warning, TEXT("NativeConstruct 후 - BaseValue: %.1f"), BaseValue);
}

void UGS_StatDataWidget::UpdateUI()
{
    UE_LOG(LogTemp, Warning, TEXT("UpdateUI - BaseValue: %.1f"), BaseValue);
    float TotalVal = BaseValue + CurrRuneValue + CurrBonusValue;
    UE_LOG(LogTemp, Warning, TEXT("총합: %.1f + %.1f + %.1f = %.1f"), 
           BaseValue, CurrRuneValue, CurrBonusValue, TotalVal);
}

결과 로그:

4. 문제 해결

5. 성과와 깨달은 점

가장 큰 교훈
언리얼 위젯의 생명주기를 제대로 이해하지 못하면 예상치 못한 버그가 생김. 특히 NativeConstruct()는 위젯이 화면에 나타날 때 호출되므로, 개발자가 직접 호출하는 초기화 함수와 순서가 꼬일 수 있음

설계 개선사항

  • 각 함수가 하나의 역할만 하도록 단일 책임 원칙 적용
  • 상태 변경을 최소화하고, 변경 지점을 명확히 함
  • 로그를 통한 디버깅의 중요성 재확인

📚 개발 참고

언리얼 위젯 생명주기 정리

1. Constructor() → 위젯 인스턴스 생성
2. NativePreConstruct() → 에디터에서 미리보기용
3. NativeConstruct() → 위젯이 화면에 추가될 때 ⚠️
4. NativeTick() → 매 프레임 (필요시)
5. NativeDestruct() → 위젯이 제거될 때

핵심 포인트

0개의 댓글