RTS

개요#
| 인원 | 기간 | 사용 기술 |
|---|---|---|
| 1인 | 2024년 3월 ~ | C++17, OpenGL |
RTS 장르에 초점을 둔 게임 엔진
문제 해결#
메모리 관리#
C++ 표준 라이브러리 사용 시 다음과 같은 문제 존재:
- 수천~수만 개의 malloc·free 호출로 인한 높은 오버헤드
- 스마트 포인터 레퍼런스 카운터 갱신 시 캐시 라인 독점 비용 발생
- 다수의 실패 가능 지점 및 OS의 개입으로 인한 성능 편차
따라서, 직접 메모리 자료구조 작성.
Windows VirtualAlloc()으로 페이지 단위 메모리를 예약하고, 스택
포인터 이동만으로 주소를 반환하는 Arena 할당자 구현.
수명이 한 프레임으로 정해지는 객체들을 한데 묶어, 매 프레임 시작 시 할당자를 통째로 초기화. 할당·해제 호출을 N번 → 1번으로 상수화.
할당했던 블록을 재사용할 수 있는 Free List·Pool을 구현해 할당·해제 오버헤드 감소.
malloc·free 대비 렌더링 데이터 처리와 개체 관리 모두 개선:
| µs/frame | malloc·free | Arena·Pool |
|---|---|---|
| 렌더링 | 106.12 | 14.88 |
| 개체 관리 | 31.29 | 23.99 |
대규모 렌더링#
100 vs 100을 시작으로 전투 규모를 확장하며 프레임 드랍 발생.
CPU와 GPU 프로파일러로 원인 분석 후, 그래픽스 디버거로 Shadow Pass의 지오메트리 셰이더 단계의 낮은 병렬성 확인. 단순한 반복 렌더링으로 전환해 15ms → 9ms로 개선.

행렬 업데이트용 GPU 메모리를 게임 종료 시까지 CPU에 매핑해 매 프레임 Map/Unmap·Fence 동기화 비용 제거. 4x4 → 3x4 행렬 압축으로 업로드 대역폭도 개선.
CPU 애니메이션 업데이트는 단위 간 의존성이 없어 parallel for로 병렬 처리, 동기화 비용도 최소화.
template <typename F>
void ParallelFor(Thread_Group& group, int64_t count, F&& func);

1000 vs 1000에서 60 FPS 달성.
| 전 | 후 | |
|---|---|---|
| 드로우 콜 수 | 10,000 | 30 |
| Shadow Pass | 15ms | 9ms |
| 600 vs 600 | 30 FPS | 100 FPS |
| 1000 vs 1000 | --- | 60 FPS |
경로탐색#
RTS의 필수 요소인 경로 탐색 구현을 위해 삼각분할 알고리즘 관련 코드 필요. 오픈 소스 라이브러리 사용을 고민하여 다음과 같은 문제 발생:
- 장애물 파괴를 위한 삭제 연산 미지원
- 지진 시뮬레이션 등이 주 목적인 무거운 코드
이에 따라 기하 라이브러리를 직접 작성.
다음과 같은 과정으로 알고리즘 구현.
- 들루네 삼각분할(CDT)로 NavMesh 생성.
- A*을 통해 경로 산출.
- Simple Stupid Funnel 알고리즘으로 경로 단순화.
타 유명 라이브러리들 대비 빠른 빌드 시간과 수행 시간, 삭제 연산 확보.
| 자체개발 | CGAL | Triangle | |
|---|---|---|---|
| 빌드 시간 (ms) | 748 | 17,805 | 3,894 |
| 삭제 연산 | O | O | X |
| 수행 시간 (ms) | 1.94 | 1.82 | 3.84 |
코드를 GitHub에 배포하여 100여 개의 스타 획득.
