카테고리 없음

TIL-2nd. 팀프로젝트 DreamProtector (8/21)WaveManager 웨이브 종료 처리 및 4차 분반수업 내용 정리

view29579 2026. 9. 17. 20:16

오늘은 기존에 구현해둔 WaveManager웨이브 종료 시 남아있는 악몽을 침대에 데미지로 반영하고, HUD의 악몽 수를 초기화하는 기능​을 추가했다.

기존 웨이브 시스템은 CurrentMonsterCountKilledMonsterCount를 이용해서 현재 웨이브의 남은 악몽 수를 계산하고 있었다.

const int32 RemainingCount =
    FMath::Max(CurrentMonsterCount - KilledMonsterCount, 0);

RemainingCount를 계산한 이유

현재 웨이브의 전체 악몽 수에서 처치한 악몽 수를 빼면 남아있는 악몽 수를 알 수 있다.

전체 악몽 수 - 처치한 악몽 수 = 남은 악몽 수

예를 들어 45마리가 스폰되고 30마리를 처치했다면:

45 - 30 = 15

따라서 남은 악몽은 15마리이다.

여기서 FMath::Max()를 사용한 이유는 계산 결과가 음수가 되는 것을 방지하기 위해서이다.

FMath::Max(CurrentMonsterCount - KilledMonsterCount, 0);

결과가 0보다 작아지더라도 최소값을 0으로 유지한다.


2. 웨이브 종료 시 침대에 Stress 적용

웨이브 제한시간이 끝났을 때 호출되는 함수인 OnWaveTimeExpired()에서 남은 악몽 수를 확인하도록 했다.

const int32 RemainingCount =
    FMath::Max(CurrentMonsterCount - KilledMonsterCount, 0);

그리고 남아있는 악몽 1마리당 침대 Stress를 10 증가시키도록 했다.

if (Bed && RemainingCount > 0)
{
    Bed->IncreaseStress(RemainingCount * 10);
}

RemainingCount * 10을 사용하는 이유

기획상 웨이브가 종료되었을 때 살아남은 악몽이 침대를 공격하는 것으로 처리하기 위해서이다.

악몽 1마리당 Stress 10이므로:

남은 악몽 1마리 → Stress +10
남은 악몽 5마리 → Stress +50
남은 악몽 10마리 → Stress +100

따라서 남은 악몽 수에 10을 곱해서 한 번에 침대에 전달했다.


3. Bed->IncreaseStress()를 사용한 이유

침대에는 이미 IncreaseStress() 함수가 구현되어 있었다.

void ABed::IncreaseStress(int32 Amount)
{
    CurrentStress += Amount;

    CurrentStress =
        FMath::Clamp(CurrentStress, 0, MaxStress);

    OnStressChganged.Broadcast(
        CurrentStress,
        MaxStress
    );

    OnBedAttacked.Broadcast();
}

WaveManager에서 침대의 Stress 값을 직접 변경하지 않고 기존 함수를 호출했다.

Bed->IncreaseStress(RemainingCount * 10);

이렇게 한 이유는 침대의 Stress 처리를 Bed 클래스가 담당하도록 하기 위해서이다.

WaveManager가 직접:

Bed->CurrentStress += ...

처럼 처리하게 되면 WaveManager가 침대 내부의 Stress 시스템까지 알아야 한다.

반면 IncreaseStress()를 사용하면 WaveManager는

"침대의 Stress를 이만큼 증가시켜줘."

라고 요청만 하면 된다.

실제 Stress 증가, 최대값 제한, HUD 알림, 침대 공격 알림은 ABed가 담당한다.

즉 역할을 나누었다.

WaveManager
→ 남은 악몽 수 계산
→ 침대에 증가량 전달

Bed
→ Stress 증가
→ 최대 Stress 제한
→ Stress 변경 알림
→ 침대 공격 알림

4. if 방어 코드를 추가한 이유

침대 객체가 연결되지 않은 상태에서 바로:

Bed->IncreaseStress(...);

를 호출하면 문제가 발생할 수 있다.

그래서 다음과 같이 방어 코드를 작성했다.

if (Bed && RemainingCount > 0)
{
    Bed->IncreaseStress(RemainingCount * 10);
}

여기서 두 가지를 확인한다.

Bed
→ 침대 객체가 존재하는가?

RemainingCount > 0
→ 실제로 남아있는 악몽이 있는가?

둘 다 만족할 때만 침대 Stress를 증가시킨다.

이번 작업을 통해 C++에서 객체를 사용하기 전에 유효한지 확인하는 방어 코드가 중요하다는 것도 다시 확인했다.


5. 웨이브 종료 후 HUD 악몽 수 초기화

기존에는 웨이브가 끝나도 HUD에 이전 웨이브의 숫자가 남아있었다.

예를 들어:

15 / 45

상태에서 웨이브가 종료되어 대기시간으로 들어가도 숫자가 그대로 표시될 수 있었다.

그래서 웨이브 종료 시:

OnMonsterCountChanged.Broadcast(
    0,
    0
);

을 호출하도록 했다.

Broadcast()를 사용한 이유

OnMonsterCountChanged는 몬스터 수가 변경되었을 때 HUD 등 다른 시스템에 알려주는 Delegate이다.

따라서 WaveManager가 HUD를 직접 찾아서 텍스트를 변경하는 대신:

WaveManager
    ↓
OnMonsterCountChanged.Broadcast()
    ↓
HUD
    ↓
악몽 숫자 변경

방식으로 연결했다.

웨이브 종료 시 0, 0을 전달하면 대기시간 동안:

00 / 00

으로 표시할 수 있다.

여기서 두 번째 값까지 0으로 전달한 이유는 단순히 남은 악몽 수만 0으로 만드는 것이 아니라 대기시간 동안 전체 악몽 수도 표시하지 않도록 하기 위해서이다.


6. 전체 흐름

최종적으로 웨이브 제한시간이 끝나면 다음 순서로 처리된다.

OnWaveTimeExpired()
        ↓
현재 웨이브의 전체 악몽 수 확인
        ↓
처치한 악몽 수 확인
        ↓
RemainingCount 계산
        ↓
남은 악몽 × 10
        ↓
Bed->IncreaseStress()
        ↓
침대 Stress 증가
        ↓
OnMonsterCountChanged.Broadcast(0, 0)
        ↓
HUD → 00 / 00
        ↓
대기시간
        ↓
다음 웨이브 시작
        ↓
새로운 몬스터 수 표시

예를 들어 Stage 2에서 45마리가 등장하고 32마리를 처치한 상태로 웨이브가 끝났다면:

45 - 32 = 13마리 생존

13 × 10 = Stress +130

HUD → 00 / 00

침대의 MaxStress가 100이므로 실제 Stress는 ABed::IncreaseStress() 내부의 FMath::Clamp()에 의해 최대 100까지만 증가한다.


7. 이번 작업에서 중요했던 점

이번 작업에서는 새로운 시스템을 크게 만드는 것보다 기존에 만들어둔 시스템을 연결하는 방식으로 구현했다.

WaveManager
→ 웨이브와 몬스터 수 관리

Bed
→ Stress 관리

HUD
→ Delegate를 통해 몬스터 수 표시

각 클래스가 자신의 역할을 담당하도록 유지하면서 필요한 부분만 연결했다.

특히 WaveManager에서 침대의 Stress 내부 값을 직접 수정하지 않고 IncreaseStress()를 호출한 것이 중요한 부분이었다.