티스토리 뷰
🟩 오늘의 목표
- FWeaponStat 구조체를 활용해 데이터 기반으로 무기 종류를 확장할 수 있는 시스템을 구축한다.
- 사격 입력 시 첫 발사 지연을 제거하고 고연사 시의 사운드 끊김 현상을 해결한다.
- TMap을 이용해 무기 교체 시에도 탄약 데이터를 보존하고, 장전 후 자동으로 사격이 재개되는 로직을 완성한다.
🟧 1. 확장형 무기 데이터 구조 (FWeaponStat)
🟦 데이터 기반 무기 확장성 확보
데이터 테이블을 연동하여 권총, 연사 라이플, 샷건 등 새로운 무기 타입을 코드 수정 없이 추가할 수 있는 기반을 마련했다. 특히 PelletCount(산탄 수)와 BulletSpread(탄퍼짐) 멤버를 도입하여 단발 사격과 샷건 로직을 하나의 컴포넌트에서 통합 처리할 수 있게 설계했다.
🟧 2. 사격 반응성 및 리듬 보정 (StartFire, Fire)
🟦 첫 발사 지연 해소 및 연사 안정화
사격 입력 시 쿨타임을 역산하여 첫 발사가 즉시 나가도록 보정하고, 타이머 오차(Jitter)를 고려한 0.8f 허용치를 적용해 고연사 중 사운드가 끊기는 현상을 해결했다.
// 첫 발사 지연 해소 및 연사 타이머 설정
void UWeaponComponent::StartFire() {
float CurrentTime = GetWorld()->GetTimeSeconds();
// 쿨타임이 이미 지났다면 LastFireTime을 역산하여 즉시 발사 보장
if (CurrentTime - LastFireTime >= CurrentStat->FireRate) {
LastFireTime = CurrentTime - CurrentStat->FireRate;
}
Fire(); // 첫 발 즉시 실행
GetWorld()->GetTimerManager().SetTimer(FireTimerHandle, this, &UWeaponComponent::Fire, CurrentStat->FireRate, true);
}
// 사격 리듬 보정 및 연타 방지
void UWeaponComponent::Fire() {
float CurrentTime = GetWorld()->GetTimeSeconds();
// 교체 딜레이 체크
if (CurrentTime - LastWeaponSwitchTime < WeaponSwitchDelay) return;
// 타이머 오차(Jitter)를 고려한 0.8f 허용치 적용 (연사 끊김 방지)
if (CurrentTime - LastFireTime < CurrentStat->FireRate * 0.8f) return;
// ... 사격 실행 및 LastFireTime 업데이트 ...
}
🟧 3. 무기별 독립 탄약 관리 (TMap, ChangeWeapon)
🟦 무기 교체 시 탄약 데이터 보존
TMap을 도입하여 무기를 교체하더라도 각 무기가 가졌던 이전 탄약 정보를 유지하도록 구현했다. 새로운 무기로 교체할 때 맵에서 데이터를 찾아 복구하거나, 처음 사용하는 무기라면 데이터 테이블의 MaxAmmo를 할당한다.
// TMap을 활용한 잔탄수 영구 보존
void UWeaponComponent::ChangeWeapon(FName NewWeaponName) {
if (bIsReloading || WeaponRowName == NewWeaponName) return; // 장전 중 교체 차단
WeaponAmmoMap.Add(WeaponRowName, CurrentAmmo); // 현재 탄약 저장
if (FWeaponStat* NewStat = WeaponStatTable->FindRow<FWeaponStat>(NewWeaponName, TEXT(""))) {
WeaponRowName = NewWeaponName;
// 맵에서 데이터를 찾아 복구하거나 처음이면 최대 탄약 할당
CurrentAmmo = WeaponAmmoMap.Contains(NewWeaponName) ? WeaponAmmoMap[NewWeaponName] : NewStat->MaxAmmo;
LastWeaponSwitchTime = GetWorld()->GetTimeSeconds(); // 교체 지연 시작
// ... 자동 사격 재개 로직 ...
}
}
🟧 4. 장전 후 사격 자동 재개 (CompleteReload)
🟦 끊김 없는 전투 흐름 설계
장전이 완료되는 즉시 마우스 클릭 상태(bHoldingFire)를 체크하여 사격이 바로 재개되도록 로직을 연결했다. 이때 LastFireTime을 조정하여 장전 직후 쿨타임 대기 없이 바로 첫 발이 나갈 수 있게 보정했다.
void UWeaponComponent::CompleteReload() {
CurrentAmmo = CurrentStat->MaxAmmo;
bIsReloading = false;
// 장전 직후 즉시 사격 가능하도록 쿨타임 초기화
LastFireTime = GetWorld()->GetTimeSeconds() - CurrentStat->FireRate;
if (bHoldingFire) StartFire(); // 마우스 유지 시 즉시 사격 재개
}
🟧 핵심 성과 및 회고
- 버그 해결 : 장전 완료 후 사격 멈춤, 무기 교체 시 탄약 리셋, 연사 사운드 끊김 문제를 모두 해결했다.
- 안정성 확보 : BeginPlay에서 시간 변수를 안전하게 초기화하여 쓰레기 값에 의한 오작동을 차단했다.
- 협업 준비 : 팀원들이 로직을 쉽게 이해할 수 있도록 모든 핵심 함수에 상세 주석 작업을 완료했다.
'내일배움캠프 Unreal_7기 > 본캠프' 카테고리의 다른 글
| [CH 3] 팀프로젝트 - 무기 및 에임 시스템 고도화 (0) | 2026.02.20 |
|---|---|
| [CH 3] 팀프로젝트 - shoulder launcher(수류탄) 시스템 구현 (0) | 2026.02.19 |
| [CH 3] 팀프로젝트 - 쿼터뷰 쌍권총 사격 및 파티클 시스템 최적화 (0) | 2026.02.10 |
| [CH 3] 팀프로젝트 - 쌍권총 연사 시스템 구현 (0) | 2026.02.09 |
| TIL - 47일 (0) | 2026.02.03 |

