BulletAnt 개발일지 (22) - 트러블슈팅(Tribe동기화, NavMesh 성능)

김펭귄·2026년 5월 17일

Today What I Learned (TIL)

목록 보기
137/139

종족 머티리얼 동기화 문제 해결

클라이언트에서 종족 머티리얼이 적용되지 않는 현상이 발생했다.

이전에는 정상 동작했었기 때문에 원인을 분석해보니,
적 스폰 위치가 멀어지면서 TribeType DataAsset의 레플리케이션 타이밍 문제가 생긴 것으로 보였다.

기존 구조는:

적 스폰
→ MulticastRPC로 머티리얼 적용

형태였다.

하지만 멀리 있는 적은 NetCullDistance 범위 밖이라 동기화되지 않은 상태였고,
그 상태에서 RPC가 실행되어봤자 동기화 되지 않았다.

그래서 MulticastRPC 대신 OnRep을 사용하여:

NetCullDistance 이내로 들어옴
→ TribeType 동기화 완료
→ OnRep 호출
→ 종족 색 적용

순서로 처리되게 수정했다.
수정 후에는 거리와 관계없이 클라이언트에서도 안정적으로 종족 색이 적용되었다.


Unreal Insights를 통한 Nav 최적화

게임을 실제로 플레이해보니, 몬스터가 스폰되고 전투가 시작되면 프레임이 심하게 떨어졌다. 특히 호스트에서 심했다.

그래서 Unreal Insights로 프로파일링을 진행했다.

확인해보니 매 틱마다 GameThread 초반에 바코드처럼 작업이 계속 찍히고 있었고,
특히:

  • SyncCompletion
  • WaitingThread

비중이 매우 컸다.

원인 분석

WaitingThread 시점에 무엇이 실행되는지 확인해보니
ExecuteBackgroundTask가 계속 돌고 있었다.

처음엔 정확히 어떤 작업인지 몰랐는데,
stat namedevents를 활성화하니 상세 정보가 보였고,
원인이 Navigation 재계산이라는 것을 확인했다.

즉, 런타임 중 틱마다 NavMesh가 갱신되고 있었던 것이다.

누가 Nav를 갱신하는가?

상황을 하나씩 분리하며 확인해봤다.

  • 적 스폰 → 문제 없음
  • 건물 생성 → 순간적인 드랍만 존재
  • 포탑 생성 후 적 접근 → 지속적인 Nav 재계산 발생

특히 포탑이 적을 따라 회전할 때마다
회전하는 메시 때문에 Nav가 계속 Dirty 처리되고 있었다.

대조군으로, 포탑 대신 벽을 설치했을 때는 NavMesh가 재갱신되지 않았다.

해결 방법

그래서:

  • 포탑의 바닥(Base) 메시만 Nav 영향 유지
  • 회전하는 포신/머리 부분은
SetCanEverAffectNavigation(false);

처리하였다.

추가로:

  • Projectile
  • 캐릭터
  • 회전 메시들

역시 Nav 영향에서 제외했다.

결과적으로 건물 바닥/천장만 Nav 영향, 나머지는 전부 제외 구조로 정리하였다.

결과

수정 후에는 런타임 Nav 재계산이 거의 사라졌고, 140ms → 13.8ms 까지 감소했다.
한 프레임 기준 약 90% 가까이 줄어든 셈이다.

물론 장기적으로는 NavModifier 기반으로 관리하는 것이 더 좋은 방향일 수 있지만,
현재 프로젝트 상황에서는 매우 효과적인 최적화였다.

profile
반갑습니다

0개의 댓글