콜라이더
고친 사람 github-actions[bot]
콜라이더는 게임 속 물체가 무엇에 부딪혔는지 물리 엔진이 알아내게 해 줍니다. 물리 엔진은 물체의 움직임과 부딪힘을 계산하는 부품입니다. 화면에 보이는 복잡한 모양 대신 상자나 공 같은 단순한 도형을 물체에 씌웁니다. 엔진은 그 도형끼리만 겹쳤는지 잽니다. 덕분에 물체가 많아도 충돌 계산이 가볍게 끝납니다.
쉽고 빠른 이해
무슨 일을 하나 — 물체가 공간에서 어디까지 차지하는지를 물리 엔진에 알려 줍니다. 걷는 캐릭터에는 길쭉한 알약 모양을, 나무 상자에는 상자 모양을 보이지 않게 씌웁니다. 부딪힐 일 없는 배경 물체에는 씌우지 않습니다.
왜 이렇게 하나 — 화면에 그리는 모양은 작은 삼각형 수천 개로 되어 있습니다. 그 삼각형끼리 하나하나 겹침을 재면 계산이 감당이 안 됩니다. 단순한 도형끼리는 계산 몇 번으로 끝납니다.
어떻게 도나
- 부딪힐 일이 있는 물체마다 단순한 도형을 씌웁니다
- 엔진은 시간을 잘게 나눠 한 칸마다 도형끼리 겹쳤는지 잽니다
- 겹쳤으면 물체를 떼어 놓고 튕기거나, 무엇이 들어왔다는 신호만 게임에 보냅니다
대가 — 도형이 화면 속 모양과 딱 맞지 않습니다. 도형이 크면 닿지 않았는데 닿은 것으로 치고, 작으면 닿았는데 지나칩니다.
상세
이삿짐을 나르는 사람은 냉장고가 현관문을 지나갈지 볼 때 손잡이나 모서리 곡선까지 따지지 않습니다. 가로·세로·높이 세 숫자만 재서 상자 하나로 보고 문틀과 견줍니다. 상자가 지나가면 냉장고도 지나갑니다.
이 절은 콜라이더가 무엇이고 왜 화면 모양과 따로 두는지부터 봅니다. 그다음 콜라이더로 쓰는 도형과 겹침을 재는 법, 물체에 붙는 방식을 차례로 따라갑니다. 끝에서는 콜라이더가 화면 모양과 어긋나서 생기는 일을 봅니다.
화면 모양과 따로 두는 충돌 모양
게임 속 물체는 화면에 그릴 모양을 갖고 있습니다. 이 모양은 작은 삼각형 수천 개를 이어 붙여 만듭니다. 이 모양이 메시입니다. 삼각형이 많을수록 물체가 매끄럽고 자세하게 보입니다.
물체끼리 닿거나 겹치는 일을 충돌이라고 합니다. 충돌은 물리 엔진이 잽니다. 물리 엔진은 물체의 움직임과 부딪힘을 계산하는 부품입니다. 메시끼리 겹침을 재려면 한쪽 삼각형 하나하나를 다른 쪽 삼각형 하나하나와 견줘야 합니다.
삼각형이 천 개씩인 물체 둘이면 견줄 쌍이 백만 개입니다. 엔진은 이 일을 시간을 잘게 나눈 한 칸마다 되풀이해야 합니다. 물체가 수십 개만 되어도 계산을 감당하지 못합니다.
그래서 물체에 단순한 도형을 하나 더 씌웁니다. 상자나 구처럼 숫자 몇 개로 나타낼 수 있는 도형입니다. 이 도형이 콜라이더입니다. 엔진은 메시를 보지 않고 콜라이더끼리만 겹침을 잽니다.
콜라이더는 화면에 그려지지 않습니다. 플레이어 눈에는 메시만 보입니다. 엔진은 콜라이더만 봅니다. 한 물체가 모양을 두 벌 들고 있는 셈입니다.
콜라이더로 쓰는 도형
도형이 단순할수록 겹침 계산이 쌉니다. 엔진이 「겹쳤다」 또는 「안 겹쳤다」고 내리는 결론이 판정입니다. 도형이 물체 모양에 가까울수록 판정이 눈에 보이는 것과 잘 맞습니다. 물체마다 둘 사이에서 고릅니다.
자주 쓰는 도형은 아래 표와 같습니다.
| 도형 | 무엇으로 나타내나 | 흔히 씌우는 물체 |
|---|---|---|
| 구 | 중심 하나와 반지름 | 공 · 돌멩이 |
| 상자 | 중심과 가로·세로·높이 | 나무 상자 · 벽 · 건물 |
| 캡슐(알약 모양) | 선분 하나와 반지름 | 사람 · 동물 캐릭터 |
| 볼록 껍질(꼭짓점을 감싼 덩어리) | 꼭짓점 여러 개 | 바위 · 자동차 |
| 메시 콜라이더 | 메시의 삼각형 전부 | 땅 · 건물 안쪽 같은 지형 |
표는 위에서 아래로 갈수록 물체 모양에 가까워지고 계산이 비싸집니다. 평면에서 움직이는 2차원 게임이라면 구 대신 원을, 상자 대신 사각형을 씁니다.
캡슐은 원기둥 양 끝에 반구를 붙인 알약 모양입니다. 선분 하나에서 반지름 거리 안쪽을 전부 채운 도형으로 볼 수 있습니다. 모서리가 없어서 계단이나 문턱의 모서리에 덜 걸립니다. 걷는 캐릭터에 많이 씌우는 까닭입니다.
상자 콜라이더는 물체를 바깥에서 감싸도록 크기를 맞춥니다. 이렇게 물체를 감싸는 상자를 바운딩 박스라고 부릅니다. 바운딩 박스는 돌릴 수 있느냐에 따라 둘로 나뉩니다.
좌표축과 나란한 채로만 두는 바운딩 박스가 AABB(Axis-Aligned Bounding Box)입니다. 이름이 곧 「좌표축에 나란한 바운딩 박스」라는 뜻입니다. 모서리가 늘 축과 나란해서 겹침 계산이 쌉니다. 대신 물체가 돌면 상자를 새로 키워야 해서 빈 공간이 늘어납니다.
물체를 따라 함께 기울어지는 바운딩 박스는 OBB(Oriented Bounding Box)입니다. 「방향을 가진 바운딩 박스」라는 뜻입니다. 물체에 더 꼭 맞는 대신 겹침 계산이 AABB 보다 비쌉니다.
볼록 껍질은 물체의 꼭짓점들을 고무줄로 팽팽하게 감싼 모양입니다. 안으로 움푹 들어간 곳이 없습니다.
이렇게 움푹한 곳이 없는 도형을 볼록하다고 합니다. 구·상자·캡슐도 모두 볼록합니다. 볼록하면 겹침을 재기가 쉬워집니다. 그 까닭은 다음 소절에서 봅니다.
메시 콜라이더는 메시의 삼각형을 손대지 않고 충돌에 씁니다. 움직이는 물체끼리 메시 콜라이더로 부딪히게 하면 계산이 크게 늘어납니다. 그래서 땅이나 건물처럼 움직이지 않는 지형에 주로 씁니다.
도형 하나로 모양이 안 맞으면 여럿을 묶습니다. 의자라면 앉는 판에 상자 하나, 다리 넷에 가는 상자 넷을 씌웁니다. 이렇게 여러 도형을 묶은 것을 복합 콜라이더라고 부릅니다.
겹쳤는지 재는 법
이 소절은 가장 단순한 구 둘로 겹침 판정을 따라갑니다. 그다음 다른 도형으로 넓힙니다.
구 둘은 중심 사이 거리가 반지름의 합보다 짧으면 겹친 것입니다. 거리를 한 번 잽니다. 그 거리를 반지름 합과 견주면 끝납니다. 구가 콜라이더 가운데 계산이 가장 싼 까닭입니다.
import math
a, ra = (0.0, 0.0), 1.0 # 중심, 반지름
b, rb = (1.5, 0.0), 1.0 # 중심, 반지름
d = math.dist(a, b) # 1.5
hit = d < ra + rb # True
두 중심은 1.5 떨어져 있고 반지름 합은 2 입니다. 거리가 더 짧으니 두 구는 겹쳤습니다. b 의 중심을 (2.5, 0.0) 으로 옮기면 거리가 반지름 합보다 길어져 hit 가 False 가 됩니다.
볼록한 도형끼리도 겹침을 적은 계산으로 잴 수 있습니다. 두 도형 사이에 평면 하나를 끼워 둘을 갈라놓을 수 있으면 둘은 겹치지 않은 것입니다.
이 평면은 직접 찾지 않고 평면에 수직인 직선 하나로 시험합니다. 두 도형을 그 직선 위에 그림자처럼 내려 봅니다. 두 그림자가 떨어져 있으면 그 사이에 평면을 끼울 수 있습니다. 이 직선을 축이라고 부릅니다.
볼록한 도형끼리는 시험할 축의 후보가 도형 모양에서 몇 개로 정해집니다. 상자라면 각 면이 바라보는 방향이 후보에 들어갑니다.
한 후보에서라도 그림자가 떨어지면 두 도형은 겹치지 않은 것입니다. 모든 후보에서 그림자가 겹치면 겹친 것입니다. 이 원리가 분리축 정리입니다.
움푹 들어간 도형에는 이 원리가 통하지 않습니다. 한 도형이 다른 도형의 움푹한 곳에 닿지 않고 들어앉아 있다고 해 봅니다. 그 사이에는 평면을 끼울 수 없어서 어느 축으로 내려도 그림자가 겹칩니다. 떨어져 있는데도 겹쳤다고 판정하게 됩니다.
오목한 물체는 볼록한 조각 여럿으로 쪼개 복합 콜라이더로 만듭니다. 이렇게 쪼개는 일이 볼록 분해입니다.
강체와 콜라이더
콜라이더는 모양만 알려 줍니다. 물체가 떨어지거나 밀려나려면 강체가 따로 붙어야 합니다.
강체는 부딪혀도 모양이 변하지 않는다고 치는 물체입니다. 질량과 속도를 갖습니다. 엔진이 그 움직임을 계산해 줍니다.
게임 속 물체 하나에는 세 가지가 따로 붙을 수 있습니다. 화면에 그릴 메시, 움직임을 계산할 강체, 겹침을 잴 콜라이더입니다. 셋은 서로 독립이라 필요한 것만 고릅니다.
어느 것을 붙이느냐에 따라 엔진이 물체를 다루는 방식이 갈립니다.
| 붙인 것 | 엔진이 하는 일 | 예 |
|---|---|---|
| 콜라이더만 | 움직이지 않고 다른 물체를 막는다 | 벽 · 바닥 |
| 콜라이더와 강체 | 떨어지고 부딪혀 튕긴다 | 굴러가는 공 · 쓰러지는 상자 |
| 메시만 | 충돌 계산에서 빠진다 | 하늘의 구름 · 먼 산 |
콜라이더만 있는 물체를 정적 바디라고 부릅니다. 부딪힐 일이 없는 물체에는 콜라이더를 붙이지 않습니다. 콜라이더가 늘면 엔진이 견줘야 할 쌍도 늘기 때문입니다.
엔진이 한 칸마다 하는 일은 두 단계로 나뉩니다. 먼저 겹친 물체 쌍을 찾습니다. 이 단계가 충돌 감지입니다. 콜라이더는 이 단계에서 쓰는 모양입니다.
다음 단계는 겹친 물체를 떼어 놓고 튕기는 충돌 응답입니다. 이 단계는 움직일 강체가 있어야 일어납니다.
트리거 콜라이더
모든 콜라이더가 물체를 밀어내지는 않습니다. 겹쳐도 밀어내지 않는 콜라이더가 있습니다. 이 콜라이더는 무엇이 들어왔다는 신호만 게임 코드에 보냅니다. 이것이 트리거 콜라이더입니다.
문 앞에 보이지 않는 상자를 놓습니다. 캐릭터가 그 상자에 들어서면 문을 엽니다. 바닥에 떨어진 아이템을 주울 때도 같은 방식입니다. 캐릭터가 아이템의 트리거 콜라이더에 닿으면 게임 코드가 아이템을 가방에 넣습니다.
충돌 레이어
서로 부딪히면 안 되는 물체도 있습니다. 내가 쏜 총알이 나 자신에게 맞으면 안 되는 경우가 그렇습니다.
그래서 콜라이더마다 무리를 하나 정합니다. 어느 무리끼리 겹침을 잴지는 표로 정해 둡니다. 이 무리를 충돌 레이어라고 부릅니다.
재지 않기로 한 무리끼리의 쌍은 계산에서 아예 빠집니다. 충돌 레이어는 판정을 고르는 수단입니다. 동시에 계산을 아끼는 수단이기도 합니다.
두 단계로 나눈 겹침 검사
물체가 많으면 콜라이더 쌍의 수가 물체 수보다 훨씬 빨리 불어납니다. 물체 백 개면 쌍이 오천 개 가까이 됩니다. 그래서 엔진은 충돌 감지를 다시 두 번에 나눕니다.
먼저 콜라이더마다 그것을 감싸는 AABB 를 하나씩 만듭니다. AABB 는 앞에서 본 것처럼 콜라이더로 직접 쓰기도 합니다. 이 단계에서는 콜라이더 모양이 무엇이든 그 바깥에 한 겹 더 씌우는 바운딩 박스로 씁니다.
AABB 끼리는 겹침을 아주 싸게 잽니다. 이걸로 멀리 떨어진 쌍을 먼저 걸러 내는 단계가 브로드 페이즈입니다.
남은 가까운 쌍만 콜라이더 모양대로 정밀하게 잽니다. 이 단계가 내로 페이즈입니다. 앞에서 본 구 둘의 거리 비교나 분리축 정리가 이 단계에서 쓰입니다.
화면 모양과의 어긋남
콜라이더는 메시를 흉내 낸 도형이라 모양이 딱 맞지 않습니다. 콜라이더가 메시보다 크면 닿지 않았는데 닿은 것으로 칩니다. 작으면 닿았는데 지나칩니다.
플레이어가 이 어긋남을 가장 먼저 알아채는 곳은 공격 판정입니다. 칼이 분명히 빗나갔습니다. 그런데 맞았다고 나오면 플레이어는 억울하게 느낍니다. 그래서 공격 판정은 몸 부위마다 작은 도형을 따로 붙여 다루기도 합니다. 이 도형이 히트박스입니다.
빠르게 움직이는 작은 콜라이더는 벽을 뚫고 지나가기도 합니다. 물리 엔진은 시간을 아주 짧은 간격으로 잘라 한 칸씩 계산합니다. 이 한 칸을 물리 스텝이라고 부릅니다.
총알이 한 스텝 사이에 얇은 벽 두께보다 멀리 날아갔다고 해 봅니다. 앞 스텝에는 벽 앞에, 다음 스텝에는 벽 뒤에 있습니다. 겹친 순간이 한 번도 없으니 엔진은 충돌을 못 봅니다. 이 현상을 터널링이라고 부릅니다.
막는 쉬운 방법은 벽을 두껍게 만들거나 스텝 간격을 줄이는 것입니다. 스텝 사이에 지나간 경로 전체를 훑어 겹침을 재는 방법도 있습니다. 이 방법을 연속 충돌 감지라고 부릅니다. 경로를 훑는 만큼 계산이 늘어서 총알처럼 속도가 큰 물체에만 켭니다.
관련 항목
콜라이더의 하위 종류
AABB · OBB · 구 콜라이더 · 캡슐 콜라이더 · 볼록 껍질 · 메시 콜라이더 · 복합 콜라이더 · 트리거 콜라이더
콜라이더끼리 겹침을 재는 처리 단계
충돌 감지 · 브로드 페이즈 · 내로 페이즈 · 바운딩 박스 · 공간 분할 · BVH · 분리축 정리 · GJK 알고리즘 · 볼록 분해 · 충돌 응답
콜라이더와 함께 물체에 붙는 구성 요소
메시 · 강체 · 정적 바디 · 키네마틱 바디 · 충돌 레이어
콜라이더 판정에서 자주 나는 오류와 그 대책
터널링 · 연속 충돌 감지 · 물리 스텝 · 고정 타임스텝 · 히트박스
콜라이더가 속하는 상위 분류
충돌 · 물리 엔진 · 강체 물리 · 게임 엔진 · 게임 개발
콜라이더를 구현한 물리 라이브러리
Box2D · PhysX · Havok · Bullet Physics · Jolt Physics
다른 이름: collider · Collider · 충돌체 · collision shape