2026. 6. 10. 20:53ㆍ구현
1. 구현 목표
Enemy AI의 원거리 공격을 멀티플레이어 환경에서 안정적으로 처리하는 것이 목표다.
이번 프로젝트의 적은 다수의 탄을 발사할 수 있고, 탄속이 즉발 히트스캔이 아니라 플레이어가 보고 피할 수 있을 정도로 느린 투사체다.
따라서 단순 LineTrace 방식이 아니라, 월드에 실제로 날아가는 것처럼 보이는 Projectile 구조가 필요했다.
또한 전투 공간에는 카오스 디스트럭션으로 파괴되는 엄폐물이 존재한다.
플레이어가 엄폐물 뒤에 숨었을 때, 탄이 엄폐물에 막히거나 파괴된 이후에는 통과하는 등 현재 서버 월드 상태를 기준으로 정확히 Hit 판정이 나야 했다.
최종 목표는 다음과 같다.
- Enemy AI가 다수의 원거리 탄을 발사할 수 있어야 함
- 탄은 플레이어가 보고 피할 수 있는 Visual Projectile이어야 함
- 서버가 최종 Hit 판정을 가져야 함
- 부서지는 엄폐물과 정확히 충돌해야 함
- 500발 이상의 탄이 존재해도 네트워크 트래픽을 줄여야 함
- Spawn/Destroy 반복으로 인한 성능 부담을 줄여야 함
2. 구현 이유
처음에는 일반적인 AActor 기반 Projectile을 스폰하고, ProjectileMovementComponent와 Replication을 사용하는 방식을 생각했다.
하지만 멀티플레이어 환경에서 Enemy AI가 대량의 탄을 발사하는 구조에서는 문제가 있었다.
500발이 넘는 Projectile Actor가 동시에 존재하면 Actor Replication, Movement Replication, Spawn/Destroy 비용이 커진다.
특히 리슨 서버 환경에서는 서버 역할을 하는 호스트 플레이어의 PC가 AI, 탄 판정, 네트워크 처리, 렌더링까지 함께 부담한다.
따라서 서버에 불필요한 Actor를 많이 만들고 복제하는 구조는 피해야 했다.
반대로 클라이언트에서만 Projectile을 만들고 서버는 시간과 위치 데이터로만 판정하는 방식도 후보였다.
이 방식은 네트워크 비용은 줄일 수 있지만, 현재 프로젝트에는 카오스 디스트럭션으로 인해 실시간으로 상태가 바뀌는 엄폐물이 존재한다.
엄폐물이 부서졌는지, 아직 막고 있는지, 어떤 충돌체가 유효한지는 서버 월드 상태가 기준이 되어야 한다.
따라서 최종 Hit 판정은 서버에서 직접 처리하는 구조가 더 적합하다고 판단했다.
결국 선택한 방향은 다음과 같다.
서버:
- Projectile을 Actor로 만들지 않고 데이터로 관리
- 위치, 속도, 수명, 충돌 판정만 처리
- 현재 서버 월드 기준으로 Sweep/Trace Hit 판정
클라이언트:
- 서버에서 전달받은 발사 이벤트를 기준으로 Visual Projectile 재생
- 실제 판정은 하지 않음
- Visual Projectile은 Pooling으로 재사용
3. 구현 방식 후보 비교
3.1 Replicated Projectile Actor 500개
가장 단순한 방식은 탄마다 AProjectile Actor를 스폰하고, Replication을 켜는 것이다.
장점
구현이 직관적이다.
Unreal의 Actor Replication, ProjectileMovementComponent, Collision Event를 그대로 사용할 수 있다.
각 탄이 독립된 Actor이기 때문에 디버깅도 쉽고, Blueprint나 Editor에서 테스트하기도 편하다.
단점
탄 수가 많아질수록 성능과 네트워크 비용이 급격히 증가한다.
500발 이상의 Projectile Actor가 동시에 존재하면 Actor Spawn, Destroy, Tick, Collision, Replication 비용이 모두 커진다.
특히 Replicate Movement를 사용하면 탄 위치가 계속 네트워크로 전송될 수 있다.
탄은 게임 판정에 중요하지만, 모든 탄의 위치를 모든 클라이언트에 계속 복제하는 것은 과하다.
제외한 이유
이번 프로젝트에서는 Enemy AI가 대량의 탄을 사용할 수 있기 때문에, 탄마다 Actor를 만들고 복제하는 방식은 확장성이 낮다고 판단했다.
평가: 비추천
이유: 구현은 쉽지만 대량 탄 처리와 네트워크 최적화에 불리함
3.2 서버 Actor Pool + Replicate Movement
두 번째 방식은 Projectile Actor를 매번 Spawn/Destroy하지 않고, 서버에서 Pool로 재사용하는 방식이다.
장점
Spawn/Destroy 비용을 줄일 수 있다.
이미 생성된 Actor를 재사용하기 때문에 GC 부담과 생성 비용을 줄이는 데 도움이 된다.
또한 Actor 구조를 유지할 수 있어 Unreal의 Collision, MovementComponent, Debugging 편의성을 어느 정도 가져갈 수 있다.
단점
Actor 수 자체는 여전히 많다.
Pooling은 Spawn/Destroy 비용을 줄이는 것이지, Actor Tick과 Replication 비용을 없애는 것은 아니다.
Replicate Movement를 그대로 사용하면 대량의 탄 위치가 계속 복제되는 문제도 남는다.
즉, Pooling만으로는 네트워크 트래픽 문제를 해결하기 어렵다.
제한적으로만 적합한 이유
탄 수가 적거나, 보스 패턴처럼 제한된 수의 Projectile을 관리하는 경우에는 사용할 수 있다.
하지만 500발 이상을 고려하는 현재 구조에서는 Actor Pool만으로는 부족하다고 판단했다.
평가: 제한적
이유: Spawn/Destroy 비용은 줄지만 Actor/Replication 비용은 여전히 큼
3.3 서버 데이터 기반 Projectile Manager + 클라 Visual Pool
최종적으로 선택한 방식이다.
서버는 Projectile을 Actor로 만들지 않고, 구조체 데이터로 관리한다.
각 Projectile은 위치, 이전 위치, 방향, 속도, 수명, 데미지, 소유자, 충돌 채널 등의 데이터만 가진다.
서버의 Projectile Manager는 일정 Tick마다 Projectile 데이터를 이동시키고, 이전 위치에서 현재 위치까지 Sweep 또는 Trace를 수행해 Hit 여부를 판정한다.
클라이언트는 서버에서 전달받은 발사 이벤트를 기반으로 Visual Projectile을 Pool에서 꺼내 재생한다.
Visual Projectile은 실제 판정에 관여하지 않고, 플레이어가 탄을 보고 피할 수 있도록 시각적 표현만 담당한다.
장점
Actor 500개를 복제하지 않아도 된다.
서버는 탄을 데이터로만 관리하기 때문에 Actor Spawn/Destroy, Actor Replication, Movement Replication 비용을 크게 줄일 수 있다.
또한 Hit 판정은 서버 월드에서 수행되므로, 카오스 디스트럭션으로 인해 엄폐물이 부서지거나 충돌 상태가 바뀌어도 서버 기준으로 정확하게 처리할 수 있다.
클라이언트는 Visual만 Pooling하면 되므로 렌더링과 연출을 가볍게 관리할 수 있다.
단점
구현 난이도가 높다.
Unreal의 기본 Projectile Actor 흐름을 쓰지 않기 때문에 Manager, Projectile Data, Visual Pool, Hit Event, Debug Draw를 직접 설계해야 한다.
또한 서버 판정 위치와 클라이언트 Visual 위치가 어긋날 수 있다.
이를 줄이기 위해 발사 시각, 시작 위치, 방향, 속도, Projectile ID 등을 클라이언트에 전달하고, 클라이언트가 동일한 방식으로 Visual을 재생해야 한다.
최종 선택 이유
이번 프로젝트에서는 대량 탄 처리와 서버 판정 정확도가 모두 중요했다.
특히 카오스 디스트럭션으로 부서지는 엄폐물이 존재하기 때문에, 클라이언트 Visual만으로 충돌을 판단하면 서버 상태와 달라질 수 있다.
따라서 서버가 현재 월드 상태를 기준으로 Projectile 이동과 Hit 판정을 처리하는 구조가 필요했다.
평가: 추천
선택 이유:
- 대량 탄 처리에 유리
- Actor Replication 비용 감소
- 서버 권한 Hit 판정 가능
- 카오스 디스트럭션 환경에서 충돌 정확도 확보
- 클라이언트는 Visual Pool로 가볍게 표현 가능
3.4 클라만 Projectile 생성 + 서버는 시간/위치 데이터로 판정
이 방식은 클라이언트가 Projectile을 생성하고 이동시키며, 서버는 발사 시각과 방향을 바탕으로 수학적으로 위치를 계산해 Hit를 판정하는 방식이다.
장점
네트워크 비용이 낮다.
서버가 모든 탄의 위치를 자주 전송하지 않아도 되고, 클라이언트는 로컬에서 즉시 Visual을 생성할 수 있다.
탄의 궤적이 단순하고 월드 충돌 변화가 적다면 매우 효율적인 방식이다.
단점
현재 프로젝트처럼 파괴되는 엄폐물이 있는 경우에는 주의가 필요하다.
서버가 시간 기반으로 탄 위치를 계산하더라도, 실제 Hit 판정은 결국 서버 월드의 충돌 상태를 기준으로 해야 한다.
만약 클라이언트 Visual과 서버 판정이 서로 다른 충돌 상태를 기준으로 움직이면, 플레이어 입장에서는 탄이 맞지 않은 것처럼 보였는데 피격되거나, 반대로 맞은 것처럼 보였는데 피격되지 않는 문제가 발생할 수 있다.
이번 프로젝트에서 최종 선택하지 않은 이유
이 방식도 충분히 좋은 방식이다.
하지만 이번 프로젝트에서는 카오스 디스트럭션으로 인해 엄폐물의 상태가 전투 중 바뀔 수 있고, 탄이 엄폐물에 정확히 막히는 것이 중요했다.
따라서 서버가 Projectile 데이터를 직접 관리하고, 매 이동 구간마다 서버 월드 기준으로 Sweep/Trace하는 방식이 더 적합하다고 판단했다.
평가: 추천 가능
이번 프로젝트에서는 차선책
이유: 네트워크 효율은 좋지만, 파괴 엄폐물 충돌 정확도 측면에서 서버 Manager 방식이 더 적합
3.5 Spawn/Destroy 반복
탄을 발사할 때마다 Actor를 Spawn하고, 충돌하거나 수명이 끝나면 Destroy하는 방식이다.
장점
구현이 가장 쉽다.
Unreal의 일반적인 Actor 생성/삭제 흐름을 그대로 사용할 수 있다.
단점
대량 탄 환경에서는 Spawn/Destroy 비용과 GC 부담이 커진다.
탄이 자주 생성되고 사라지면 프레임 드랍이나 메모리 관리 비용이 증가할 수 있다.
제외한 이유
이번 구조는 대량의 탄을 다루기 때문에 Spawn/Destroy 반복 방식은 적합하지 않다.
평가: 비추천
이유: 대량 탄 환경에서 생성/삭제 비용이 큼
4. 전체 구조
최종 구조는 서버 판정과 클라이언트 시각 표현을 분리하는 방식이다.
Enemy AI
└─ 사격 결정
↓
Server Projectile Manager
└─ Projectile Data 생성
└─ 위치 갱신
└─ Sweep/Trace Hit 판정
└─ Hit 발생 시 데미지 처리
↓
Network Event
└─ 발사 이벤트 전달
└─ Hit 이벤트 전달
↓
Client Visual Projectile Pool
└─ Visual Projectile 재생
└─ Hit 연출 재생
서버는 Projectile을 Actor로 스폰하지 않는다.
대신 FServerProjectileData 같은 구조체 배열로 관리한다.
클라이언트는 서버에서 전달받은 발사 이벤트를 기반으로 Visual Projectile을 Pool에서 꺼내 이동시킨다.
이 Visual은 충돌 판정에 사용하지 않고, 플레이어에게 탄의 위치와 방향을 보여주는 역할만 한다.
서버 Hit가 발생하면 서버는 데미지 처리를 수행하고, 필요한 경우 클라이언트에 Hit FX 이벤트를 전달한다.
5. 에디터 설정
에디터에서는 다음 요소를 준비한다.
Enemy Character
- 무기 장착 소켓 설정
- Muzzle Socket 위치 확인
- 사격 애니메이션 또는 Montage 연결
Weapon Mesh
- Muzzle Socket 추가
- 탄 발사 시작 위치로 사용
Collision Channel
- Projectile 전용 Trace Channel 또는 Object Channel 설정
- Pawn, WorldStatic, Destructible Geometry와의 충돌 반응 설정
Niagara / Static Mesh
- Visual Projectile 효과
- Hit Impact 효과
- Pool에서 재사용 가능한 형태로 구성
Chaos Destruction
- 부서지는 엄폐물의 Collision 설정 확인
- 서버에서 충돌 판정 가능한 상태인지 확인
중요한 점은 Visual Projectile의 충돌 설정이다.
클라이언트 Visual은 판정용이 아니므로 충돌을 꺼두거나 Overlap 정도로 제한하는 것이 좋다.
실제 Hit 판정은 서버 Projectile Manager의 Sweep/Trace 결과를 기준으로 처리한다.
6. 구현
구현 1단계: 서버에서 원거리 공격 발사 시점을 감지하고, 총구에서 직선 탄도를 생성·수명 관리하는 것
- 공격 Montage Notify마다 정확히 한 발 생성된다.
- 무기의 S_Muzzle에서 시작한다.
- AI Target을 향해 직선으로 이동한다.
- 서버 Manager가 Actor 없이 구조체 배열로 관리한다.
- 수명이 끝나면 제거된다.
- Debug Draw로 궤적을 확인할 수 있다.
'구현' 카테고리의 다른 글
| 26.06.26(금) (0) | 2026.06.26 |
|---|---|
| [UE5] Enemy AI 원거리 공격을 위한 서버 데이터 기반 Projectile Manager 구현 - 3 (0) | 2026.06.12 |
| [UE5] Enemy AI 원거리 공격을 위한 서버 데이터 기반 Projectile Manager 구현 - 2 (0) | 2026.06.11 |
| [UE5] FABRIK로 무기 소켓 기반 Left Hand IK 구현하기 (0) | 2026.06.09 |