HOTFIX
2.5D 슈팅 탄막 게임
2.5D 슈팅 탄막 게임
HOTFIX는 Unreal Engine 5로 개발한 2.5D 탑다운 슈팅 게임입니다. 플레이어는 1 · 2 · 3 스테이지를 차례로 진행한 뒤 마지막 보스 스테이지에 도전하며, 게임 내 AI가 매 스테이지마다 플레이어의 플레이 데이터를 분석하여 실시간으로 난이도를 조정합니다.
개발 환경
C++, Unreal Engine
개발 인원
기획1 아트 2 개발1
Steam
-----------
1. AI 구현
(1) 근거리 몬스터
플레이어를 지속적으로 추격하는 근접 추적 몬스터
본체와 분리된 별도 데미지 콜리전을 두어 접촉 시 피해 부여
사전 경고 없이 접촉만으로 위협을 주는 압박형 근접 유형
(2) 원거리 몬스터
접촉 피해 없이 거리를 두고 교전하는 원거리 유형
공격 간격(쿨다운)을 두고 공격 애니메이션을 재생
애니메이션 특정 프레임에 맞춰 플레이어 방향으로 투사체 발사
(3) 자폭형 몬스터
접촉 피해 없이 플레이어를 빠르게 추격하는 고속 유형
근접 도달 또는 체력 소진 시 Telegraph로 사전 범위 표시 후 자폭
자폭 피해가 플레이어와 주변 적 모두에게 적용되는 광역 데미지
(4) 보스 몬스터
맵 중앙에 고정 배치되어 4종 패턴을 운용하는 스테이지 보스
레이저 · 몬스터 소환 · 광역 폭발 · 연쇄 폭발 패턴을 순환 (대부분 Telegraph로 사전 표시)
체력 50% 이하 진입 시 2페이즈로 전환되어 패턴 출력 간격이 가속
2. 버프/디버프 시스템
스테이지 클리어 성적(점수 비율)이 기준치 이하면 플레이어에게 버프를, 초과하면 이후 적에게 디버프를 부여해 실력에 따라 난이도를 자동 조절.
GameInstanceSubsystem이 버프/디버프를 GameplayEffect로 적용하고, 효과·아이콘·텍스트를 FBuffRow 데이터테이블로 분리해 기획자가 코드 수정 없이 콘텐츠를 추가 가능.
획득한 버프는 맵 이동으로 ASC가 재생성돼도 재적용하고, 디버프는 이후 스폰되는 적에게 순차 적용하며, 신규 게임 시작 시 전체 초기화하도록 생명주기를 관리.
보유 버프(-5%)·디버프(+10%) 개수를 최종 점수에 반영해, 버프를 덜 받고 디버프를 감수할수록 높은 점수를 얻는 리스크-리워드 구조를 구현.
3. 각종 연출 시스템
(1) 카메라 쉐이킹
엔진 기본 셰이크 프레임워크 대신 Top-Down 시점에 필요한 X/Y 2축 흔들림만 APlayerCameraManager::ApplyCameraModifiers에서 직접 구현해, 매 프레임 랜덤 오프셋을 카메라 위치에 적용.
경과 시간에 비례해 흔들림 세기를 1→0으로 선형 감쇠시키고, 지속시간을 최소값으로 클램프해 0 나누기를 방지하는 등 안정성을 확보.
UBlueprintFunctionLibrary 기반 PlayCameraShake(세기·지속시간 파라미터)로 진입점과 실제 로직을 분리해, 플레이어 피격·스킬 시전·폭탄 폭발 등 어디서든 C++/블루프린트로 호출 가능하게 구성.
(2) 히트 스탑 / 머티리얼 조정
플레이어 피격 순간 SetGlobalTimeDilation으로 게임 시간 배율을 0에 가깝게 낮춰 화면 전체를 순간 정지시켜 타격감을 극대화
시간 배율이 0이면 일반 타이머도 멈춰 복구가 불가능한 문제를, 시간 배율의 영향을 받지 않는 GetRealTimeSeconds()로 종료 시점을 판정해 정지 중에도 정확히 원래 배율로 복구하도록 구현.
GAS 어트리뷰트 델리게이트에 연동해, 피격 시 머티리얼의 Damage.Intensity 파라미터를 1로 세팅한 뒤 매 프레임 0으로 선형 보간해 피격 연출을 표현하며, 플레이어·적이 공유하는 베이스 클래스에 구현해 재사용성을 확보
MID를 최초 1회만 생성해 재사용하고, 경과 시간 변수를 음수로 두어 비재생 상태를 표시함으로써 불필요한 매 프레임 연산을 방지하는 등 성능을 고려해 최적화.
증상
스테이지 1에서 획득한 버프가 다음 스테이지로 넘어가면 사라지고 스탯이 기본값으로 돌아옴
스테이지가 진행될수록 누적되어야 할 버프가 맵 이동마다 매번 초기화됨
원인
스테이지 전환을 OpenLevel로 처리하면서 PlayerState가 파괴·재생성됐고, ASC가 PlayerState에 붙어있어 함께 새로 생성됨
그 결과 버프로 적용해둔 GameplayEffect가 파괴된 옛 ASC에 남아, 새 ASC에는 아무 버프도 존재하지 않음
해결
레벨이 바뀌어도 살아남는 GameInstanceSubsystem에 획득한 버프 원본을 누적 저장해 영속 저장소로 삼음
ASC가 새로 초기화되는 시점(PPlayerState::InitAbilities)에 저장된 버프를 전부 다시 적용해 맵 이동 후에도 버프가 유지되도록 했음
증상
UI를 닫고 게임으로 돌아온 뒤, 마우스를 천천히(정상적으로) 누르면 입력이 아예 전달되지 않음
빠르게 연타할 때만 일부 입력이 전달됐고, 그것도 온전히 다 들어오지 않고 들쭉날쭉했음
원인
bShowMouseCursor=true라 커서가 떠 있으면 캡처가 매 클릭마다 새로 잡히는데, 기본 FInputModeGameOnly는 그 캡처를 유발하는 마우스 다운을 매번 소비(consume)했음
정상 클릭은 항상 캡처용으로 먹혀 전달되지 않았고, 빠른 연타만 캡처 해제 타이밍을 우연히 비껴가 일부가 통과했음
해결
입력 모드 복귀 시 SetConsumeCaptureMouseDown(false)를 지정해, 캡처를 유발하는 마우스 다운을 소비하지 않도록 했음
클릭 속도와 상관없이 모든 마우스 입력이 게임 입력으로 온전히 전달되게 됐음
2026 GNGC 글로벌 게임잼 대상 수상