Unreal 개발 본 캠프 58일차

HappyCircle·2026년 2월 24일

Unreal 개발

목록 보기
75/163

📘 TIL – H-Index, 몬스터 SFX/VFX 적용, WaveId 자동 갱신 로직 및 GameMode 수정


🧠 1️⃣ 코딩테스트 – H-Index

📌 문제 핵심

  • h번 이상 인용된 논문이 h편 이상
  • 나머지는 h번 이하
  • 가능한 h의 최댓값

겉보기엔 조건 문제처럼 보이지만,
실제로는 정렬 후 개수 비교 문제다.


❌ 비효율적 접근

  • h 값을 0부터 n까지 하나씩 증가시키며 조건 검사
  • 매번 배열을 다시 세거나 조건 체크
  • 중첩 반복으로 구조 복잡

✅ 구조적 접근

  1. citations 오름차순 정렬
  2. i번째 논문을 기준으로:
    • 남은 논문 수 = n - i
    • 해당 논문의 인용 수 = citations[i]
  3. citations[i] ≥ n - i 이면
    → h = n - i 성립

💻 정석 코드

int solution(vector<int> citations)
{
    sort(citations.begin(), citations.end());
    int n = citations.size();

    for (int i = 0; i < n; i++)
    {
        int h = n - i;
        if (citations[i] >= h)
            return h;
    }

    return 0;
}

🧠 인사이트

  • 조건 문제처럼 보여도 결국 “정렬 후 개수 비교”
  • 수학적 조건을 코드로 옮기면 반복이 사라진다
  • 정렬이 사고를 단순화한다

🎮 2️⃣ 몬스터 SFX / VFX 적용 및 에셋 추가


📌 작업 목표

  • 전투 피드백 강화
  • 타격/사망/투사체에 VFX 적용
  • 타격/발소리/사망 SFX 적용
  • AnimSet 기반으로 데이터화

🔥 AnimSet 확장 구조

UPROPERTY(EditDefaultsOnly)
USoundBase* HitSFX;

UPROPERTY(EditDefaultsOnly)
USoundBase* DeathSFX;

UPROPERTY(EditDefaultsOnly)
UNiagaraSystem* HitVFX;

UPROPERTY(EditDefaultsOnly)
UNiagaraSystem* DeathVFX;

🎯 타격 시 적용

UGameplayStatics::PlaySoundAtLocation(
    this,
    AnimSet->HitSFX,
    GetActorLocation()
);

UNiagaraFunctionLibrary::SpawnSystemAtLocation(
    GetWorld(),
    AnimSet->HitVFX,
    HitLocation
);

🧠 구조적 의미

  • BP에서 직접 붙이지 않음
  • AnimSet을 통해 타입별 분기
  • 데이터 기반 확장 유지

🎮 3️⃣ 몬스터 Spawner – WaveId 자동 갱신 로직 추가


📌 기존 구조 문제

  • WaveId를 수동으로 StartWave(FName) 호출
  • 다음 웨이브 전환을 외부에서 제어

→ 관리 포인트 분산


✅ 개선 목표

Spawner 내부에서 WaveId를 자동 갱신


🔧 구조 개편 개념

  • 현재 웨이브 인덱스 관리
  • Wave 종료 시 다음 WaveId 자동 계산
  • 내부 상태로 Round / WaveIndex 추적

💻 개념 코드

void APotatoMonsterSpawner::AdvanceWave()
{
    CurrentWaveIndex++;

    if (CurrentWaveIndex >= WaveIdList.Num())
    {
        OnAllWavesFinished();
        return;
    }

    StartWave(WaveIdList[CurrentWaveIndex]);
}

🎯 장점

  • 외부 GameMode에서 세부 WaveId 직접 제어 불필요
  • Spawner가 “웨이브 흐름 관리자” 역할 수행

🎮 4️⃣ 플레이어 공격 대상 반영


📌 목표

기존:

  • 몬스터 → Warehouse만 공격

추가:

  • 플레이어도 공격 대상에 포함

🔧 구조 변경 포인트

  • BTService_UpdateAttackTarget 수정
  • Target 후보군에 Player 추가
  • 거리 / 우선순위 판단 로직 확장

💻 개념 로직

if (DistanceToPlayer < DistanceToWarehouse)
{
    Blackboard->SetValueAsObject(TargetKey, Player);
}
else
{
    Blackboard->SetValueAsObject(TargetKey, Warehouse);
}

🧠 설계 의미

  • Target을 “단일 고정 목표”가 아닌
  • “동적 판단 대상”으로 전환

AI 유연성 증가


🎮 5️⃣ WaveId 자동 갱신에 따른 GameMode 수정


📌 기존 구조

GameMode가:

  • 웨이브 시작
  • 종료 판단
  • 다음 웨이브 호출

→ GameMode 책임 과다


✅ 변경 구조

Spawner가 웨이브 흐름 관리
GameMode는 상위 상태만 관리


🔧 수정 방향

  • GameMode에서 직접 StartWave 호출 최소화
  • Spawner 내부 이벤트 기반 흐름
Spawner->OnWaveFinished.AddDynamic(
    this,
    &AGameMode::HandleWaveFinished
);

GameMode는:

  • 전체 라운드 종료
  • 게임 클리어/패배 처리만 담당

🧠 아키텍처 개선 효과

이전이후
GameMode 중심 제어Spawner 중심 제어
WaveId 수동 관리WaveId 자동 갱신
책임 혼합역할 분리

🎯 6️⃣ 오늘의 전체 정리

🧠 코딩테스트

  • H-Index는 정렬 후 조건 비교 문제
  • 수학적 정의를 그대로 코드로 변환

🎮 게임 개발

  • AnimSet 기반 SFX/VFX 적용
  • 전투 피드백 완성도 상승
  • Spawner 내부 Wave 흐름 자동화
  • Player를 동적 공격 대상으로 반영
  • GameMode 책임 축소 및 구조 개선

profile
개발합시다!

0개의 댓글