Quick Flow
broad phase는 충돌을 확정하는 알고리즘이 아니라, 모든 객체 쌍을 비교하기 전에 가능성 있는 후보만 만드는 단계입니다. false positive는 narrow phase가 걸러낼 수 있지만, false negative는 눈에 보이는 hit를 놓치므로 허용하면 안 됩니다.
object bounds 업데이트
-> grid / hash / tree에서 겹치는 cell 또는 node를 찾음
-> 후보 pair를 중복 없이 수집
-> narrow phase에서 shape·layer·rule을 검사
-> hit / response| 월드와 query | 먼저 고를 구조 | 반드시 측정할 값 |
|---|---|---|
| 객체가 적거나 병목이 없음 | 전체 비교 | frame time과 pair 수 |
| 크기가 비슷하고 넓게 분포 | uniform grid | cell당 후보 수 |
| sparse한 큰 월드 | spatial hash / chunk | hash churn과 memory |
| 지역별 밀도·query 크기가 크게 다름 | quadtree·octree·BVH | update와 query 비용 |
| 대부분 정적 geometry | build-once index | rebuild 조건 |
| 투사체가 빠르게 이동 | swept query / continuous 검사 | tunnel 재현 test |
등록과 query 계약
cell size는 평균 object size, interaction range, query radius에 맞춥니다. cell이 크면 후보가 다시 많아지고, 작으면 큰 object의 여러 cell 등록과 이동 갱신이 늘어납니다. 하나의 object가 여러 cell에 닿으면 모든 겹친 cell에 넣거나 query 범위를 bounds만큼 확장합니다. 중심 cell 하나만 등록하면 경계에서 false negative가 납니다.
후보 pair는 object ID를 정렬한 key처럼 중복 제거 기준을 둡니다. 같은 두 object가 여러 cell을 공유할 수 있고, self pair와 이미 파괴된 object도 걸러야 합니다. broad phase가 받은 position·bounds가 언제 갱신되는지도 정합니다. physics step 직전의 bounds를 query하면서 render update의 position을 섞으면 한 frame 늦은 hit가 생길 수 있습니다.
Unity 물리와 직접 구조
Unity Physics.OverlapSphere 같은 query는 collider와 layer·trigger policy를 기준으로 후보를 가져오는 엔진 API입니다. 매 호출의 allocation 여부와 NonAlloc API의 buffer truncation 계약을 profile하며, 직접 grid를 만들어 physics를 재구현하지 않습니다. 직접 공간 분할은 대규모 AI proximity, custom 2D rules, server simulation처럼 Unity physics query만으로 비용이나 규칙을 제어하기 어려울 때 후보입니다.
정적 wall·tile·navigation data와 매 frame 움직이는 projectile·enemy를 한 index에 넣을 필요는 없습니다. 정적 index는 build 뒤 재사용하고, 동적 index는 삽입·제거가 단순한 grid/hash로 두면 update 범위를 좁힐 수 있습니다. scene unload에는 등록을 해제하거나 scope 자체를 폐기해 destroyed object ID가 남지 않게 합니다.
실패를 재현하기
큰 boss가 cell 경계에 있고, projectile이 이웃 cell을 가로질러 빠르게 이동하고, query radius가 cell 크기보다 큰 test를 만듭니다. 후보 수, narrow phase 호출 수, index update time을 Profiler에서 함께 봅니다. object 수가 적다면 전체 비교가 더 단순하고 충분히 빠를 수 있으므로, 복잡한 tree를 병목 확인 전에 도입하지 않습니다.
cell 수가 많아졌다는 사실은 최적화 성공이 아닙니다. 실제 접촉이 후보에서 빠지지 않는지 먼저 test하고, 그 뒤에 candidate pair·index update·narrow phase 시간을 함께 비교하세요.
참고 링크
2 sources