
처음에는 파괴 후 분리된 메쉬(Connected Component)들에 고유 ID를 부여하여 서버와 연동하려 했습니다. 논리적으로는 완벽해 보였지만, 실제 테스트 결과는 참담했습니다. 원인은 바로 Floating Point(부동 소수점) 오차였습니다.
고민 끝에 레인보우 식스 시즈의 기술 컨퍼런스 내용을 다시 복기했습니다. 레인보우 식스 시즈는 벽면(2D)을 그리드화하여 파괴를 관리합니다. 저는 이를 3D 공간으로 확장하여 메쉬 내부를 셀(Cell) 단위로 분할 관리하는 방식을 채택했습니다.
수학적으로 복잡한 메쉬의 정점 정보를 맞추려 노력하는 대신, "어떤 셀이 파괴되었는가"라는 확정적인 정수(Integer) 데이터를 동기화함으로써 오차 문제를 근본적으로 해결했습니다.

cell 근사 전 기본 메쉬

cell 분할을 적용한 메쉬(파란색이 Alive Cell,초록색이 Anchor Cell)
RealtimeDestructure은 파괴 데이터를 두 가지 트랙으로 분리하여 전송합니다.
서버에서의 처리 흐름
1. Boolean 처리 완료
2.MulticastApplyOpsCompact()→ 메시 시각적 구멍 뚫기 (시각)
3.MulticastDestroyedCells()→ Cell 상태 갱신 (충돌/구조 데이터)
서버에서 파괴된 셀의 ID 목록을 브로드캐스트하면, 클라이언트는 이를 받아 세 가지 핵심 작업을 수행합니다.
/** 파괴된 Cell ID 목록을 모든 클라이언트에 동기화 */
UFUNCTION(NetMulticast, Reliable)
void MulticastDestroyedCells(const TArray<int32>& DestroyedCellIds);
CellId를 Destroyed 상태로 변경합니다. (서버와 1:1 일치)
파괴 처리가 된 셀(빨간색은 Destroyed Cell)
메쉬의 정점 하나하나를 똑같이 맞추려 했던 방법을 버리고, 그리드 기반의 상태 동기화로 메시를 근사한 결과는 성공적이었습니다.
다음 포스팅에서는 이 Cell 데이터를 활용해 파편 처리와 메쉬 아일랜드를 어떻게 제거 할 수 있었는지에 대해 다뤄보도록 하겠습니다.