본문으로 건너뛰기
CHOI HONGSU
1 min read

로비 디더

 

카메라-플레이어 사이 장애물을 반투명 처리하는 디더링 시스템의 물리 엔진 비용을 분석하고, 쿼리 방식·계산 주기 두 축에서 개선안을 측정 — PhysicsFixedUpdate 0.2~0.4ms 감소, GC 할당 약 30% 감소.

제목

기존 구조

Kinematic Rigidbody + BoxCollider(Trigger) 방식. 매 프레임 콜라이더의 크기/위치/회전이 바뀌므로 PhysX 가 Broadphase 트리에서 이 콜라이더를 매번 재배치하고, 씬의 모든 트리거 콜라이더와의 겹침을 상시 검사한다. 콜라이더가 살아있는 한 물리 엔진이 계속 일하는 구조.

개선 가설

"필요한 순간만 PhysX BVH 를 읽기 전용 쿼리하면 Broadphase 재배치 비용이 사라진다."

OverlapBox / RaycastAll 둘 다 PhysX 내부 BVH 를 즉시 조회하는 read-only API. 상시 등록된 콜라이더가 없으므로 매 프레임 Broadphase 갱신이 필요 없고, 쿼리를 호출하는 그 순간만 비용이 발생한다.

추가로 계산 주기도 함께 변경했다. 디더링은 시야 가림 판정이고, 카메라 / 플레이어가 한 프레임에 크게 움직이지 않으므로 30프레임 간격(약 0.5초)로 충분.

측정 결과 (S21 / 상옵 60FPS)

방식PhysicsFixedUpdate 평균피크 측정GC 할당 수
기존 콜라이더 (매 프레임)0.50~0.90 ms0.91 ms @ PL 18ms495,748
OverlapBox (30프레임)0.30~0.50 ms0.37 ms @ PL 17ms352,203
Raycast (30프레임)0.30~0.50 ms0.48 ms @ PL 16ms367,052

분석 — 진짜 효과는 어디서 왔는가

수치만 보면 "Broadphase 비용 제거가 컸다"라고 결론지을 법한데, 실제로는 계산 주기 단축의 영향이 더 컸다.

  • 쿼리 방식 변경(콜라이더→OverlapBox)을 매 프레임으로 유지했다면 절감폭이 훨씬 작았을 것
  • GC 절감 30% 도 30프레임 간격이라는 호출 수 자체 감소가 주 원인 (495K→352K)
  • 측정 편차도 있어 단일 시점 비교는 위험 — 누적 평균으로 판단

엔지니어링 관점에서 의미 있는 발견: 알고리즘 자체를 갈아엎기 전에 호출 빈도부터 줄이는 것이 1차 옵션. PhysX 같은 잘 만들어진 엔진의 단일 쿼리 비용은 이미 작고, 비대해 보였던 게 누적 호출 빈도 문제였던 케이스.

결정

RaycastAll(카메라→플레이어 방향, 거리=세그먼트 길이) + 30프레임 간격 채택.

  • OverlapBox 와 평균 성능 동일하지만 의미 단위(시선 차단 = ray)와 더 맞음
  • 줌 레벨별 거리/반경 설정은 cameras.proto 데이터 그대로 활용

회고

  • 측정 편차가 컸다 — 같은 씬에서도 카메라 워크에 따라 ±0.2ms 흔들림. 누적 평균과 피크를 같이 봐야 신뢰 가능.
  • "콜라이더 기반은 비싸 보이니 raycast 로 바꾸자" 같은 직관에 빠지지 않고, 변경 축을 두 개로 분해해서 (쿼리 방식 / 호출 주기) 각각 측정한 것이 의미 있었음.
  • 정작 큰 절감은 호출 주기에서 나왔다 — 단순한 변경(상수 하나)이 구조 변경보다 효과가 컸음을 인정하는 정직한 결론

Implementation

  1. 01

    기존 콜라이더 기반 (매 프레임)

  2. 02

    OverlapBox 쿼리 (30 프레임 간격)

  3. 03

    Raycast 쿼리 (30 프레임 간격)

30프레임 계산 시 딜레이 영상